请问几位GG,怎么样才能使用DOS命令PING (50分)

  • 主题发起人 主题发起人 jxcy001
  • 开始时间 开始时间
J

jxcy001

Unregistered / Unconfirmed
GUEST, unregistred user!
我想知道怎么样在DELPHI里使用PING命令

如果PING不通的话,程序怎么判断呢?

还有如果PING通的话,程序怎么显示该IP地址的速度?

请各位GG帮帮我吧,

还是老样子, 最好有源程序哦~~

小妹先谢谢了~~~
 
用ICS组件中的PING控件
或者
从 ICMP.DLL 中调用
下面是一个例子

How to create the PING functionality from ICMP.DLL
Answer:
A Little PING application.

Once a received a email from a VB developer asking how we can ping a host from a delphi application.
But Whats´s PING ?
Ping is a protocol for testing whether a particular computer is connected to the Internet by sending a packet to its Internet Protocol (IP) address and waiting for a response.
We build a little application that implements the ping funcionality. To do that we use the ICMP protocol implemented on ICMP.DLL.
ICMP - Internet Control Message Protocol. The ICMP delivers error and control messages from hosts to the requesters. An ICMP test can determine whether a destination is reachable and responding.

1. open Delphi;
2. On a new project, Add a Tbutton, a Tedit and a Tmemo in your form;
3. Insert the “winsock” in the uses clausule;
4. Declare a record constant to put the IP head:
type
IPINFO = record
Ttl :char;
Tos :char;
IPFlags :char;
OptSize :char;
Options :^char;
end;
5. Declare a record constant to put the ICMP package:
type
ICMPECHO = record
Source :longint;
Status :longint;
RTTime :longint;
DataSize:Shortint;
Reserved:Shortint;
pData :^variant;
i_ipinfo:IPINFO;
end;

6. Declare the functions/procedures that you wiil call from ICMP.DLL
TIcmpCreateFile = function():integer; {$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpCloseHandle = procedure(var handle:integer);{$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpSendEcho = function(var handle:integer; endereco:DWORD; buffer:variant; tam:WORD; IP:IPINFO; ICMP:ICMPECHO; tamicmp:DWORD; tempo:DWORD):DWORD;{$IFDEF WIN32} stdcall; {$ENDIF}

7. In the Tbutton´s Onclick event insert this code::

procedure TForm1.Button1Click(Sender: TObject);
var
wsadt : wsadata;
icmp :icmpecho;
HNDicmp : integer;
hndFile :integer;
Host :PHostEnt;
Destino :in_addr;
Endereco :^DWORD;
IP : ipinfo;
Retorno :integer;
dwRetorno :DWORD;
x :integer;

IcmpCreateFile : TIcmpCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;

begin
if (edit1.Text = '') then begin
Application.MessageBox('Enter a HostName ro a IP Adress',
'Error', MB_OK);
exit;
end;
HNDicmp := LoadLibrary('ICMP.DLL');
if (HNDicmp <> 0) then begin
@IcmpCreateFile := GetProcAddress(HNDicmp,'IcmpCreateFile');
@IcmpCloseHandle := GetProcAddress(HNDicmp,'IcmpCloseHandle');
@IcmpSendEcho := GetProcAddress(HNDicmp,'IcmpSendEcho');
if (@IcmpCreateFile=nil) or (@IcmpCloseHandle=nil) or (@IcmpSendEcho=nil) then begin
Application.MessageBox('Error getting ICMP Adress’,'Error', MB_OK);
FreeLibrary(HNDicmp);
end;
end;
Retorno := WSAStartup($0101,wsadt);

if (Retorno <> 0) then begin
Application.MessageBox('Can´t Load WinSockets','WSAStartup', MB_OK);
WSACleanup();
FreeLibrary(HNDicmp);
end;

Destino.S_addr := inet_addr(Pchar(Edit1.text));
if (Destino.S_addr = 0) then begin
Host := GetHostbyName(PChar(Edit1.text));
end
else begin
Host := GetHostbyAddr(@Destino,sizeof(in_addr), AF_INET);
end;

if (host = nil) then begin
Application.MessageBox('Host not found','Error', MB_OK);
WSACleanup();
FreeLibrary(HNDicmp);
exit;
end;
memo1.Lines.Add('Pinging ' + Edit1.text);

Endereco := @Host.h_addr_list;

HNDFile := IcmpCreateFile();
for x:= 0 to 4 do begin
Ip.Ttl := char(255);
Ip.Tos := char(0);
Ip.IPFlags := char(0);
Ip.OptSize := char(0);
Ip.Options := nil;

dwRetorno := IcmpSendEcho(
HNDFile,
Endereco^,
null,
0,
Ip,
Icmp,
sizeof(Icmp),
DWORD(5000));
Destino.S_addr := icmp.source;
Memo1.Lines.Add('Ping ' + Edit1.text);
end;


IcmpCLoseHandle(HNDFile);
FreeLibrary(HNDicmp);
WSACleanup();
end;

This code is not complete functional, sometimes it´s doesn´t work with Hostnames, only with IP adresses. For NT users don´t use the IcmpCloseHandle function. If you have some idea to make this code work better, mail me.

That´s All…..

Now, the complete unit ´s code:

----------------------------------
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
winsock, StdCtrls;

type
IPINFO = record
Ttl :char;
Tos :char;
IPFlags :char;
OptSize :char;
Options :^char;
end;

type
ICMPECHO = record
Source :longint;
Status :longint;
RTTime :longint;
DataSize:Shortint;
Reserved:Shortint;
pData :^variant;
i_ipinfo:IPINFO;
end;

TIcmpCreateFile = function():integer; {$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpCloseHandle = procedure(var handle:integer);{$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpSendEcho = function(var handle:integer; endereco:DWORD; buffer:variant; tam:WORD; IP:IPINFO; ICMP:ICMPECHO; tamicmp:DWORD; tempo:DWORD):DWORD;{$IFDEF WIN32} stdcall; {$ENDIF}


type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public

end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
wsadt : wsadata;
icmp :icmpecho;
HNDicmp : integer;
hndFile :integer;
Host :PHostEnt;
Destino :in_addr;
Endereco :^DWORD;
IP : ipinfo;
Retorno :integer;
dwRetorno :DWORD;
x :integer;

IcmpCreateFile : TIcmpCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;

begin
if (edit1.Text = '') then begin
Application.MessageBox('Digite um HostName ou um End. IP',
'Error', MB_OK);
exit;
end;
HNDicmp := LoadLibrary('ICMP.DLL');
if (HNDicmp <> 0) then begin
@IcmpCreateFile := GetProcAddress(HNDicmp,'IcmpCreateFile');
@IcmpCloseHandle := GetProcAddress(HNDicmp,'IcmpCloseHandle');
@IcmpSendEcho := GetProcAddress(HNDicmp,'IcmpSendEcho');
if (@IcmpCreateFile=nil) or (@IcmpCloseHandle=nil) or (@IcmpSendEcho=nil) then begin
Application.MessageBox('Erro pegando endereços ICMP','Error', MB_OK);
FreeLibrary(HNDicmp);
end;
end;
Retorno := WSAStartup($0101,wsadt);

if (Retorno <> 0) then begin
Application.MessageBox('Não foi possível carregar WinSockets','WSAStartup', MB_OK);
WSACleanup();
FreeLibrary(HNDicmp);
end;

Destino.S_addr := inet_addr(Pchar(Edit1.text));
if (Destino.S_addr = 0) then begin
Host := GetHostbyName(PChar(Edit1.text));
end
else begin
Host := GetHostbyAddr(@Destino,sizeof(in_addr), AF_INET);
end;

if (host = nil) then begin
Application.MessageBox('Host não encontrado','Error', MB_OK);
WSACleanup();
FreeLibrary(HNDicmp);
exit;
end;
memo1.Lines.Add('Pinging ' + Edit1.text);

Endereco := @Host.h_addr_list;

HNDFile := IcmpCreateFile();
for x:= 0 to 4 do begin
Ip.Ttl := char(255);
Ip.Tos := char(0);
Ip.IPFlags := char(0);
Ip.OptSize := char(0);
Ip.Options := nil;

dwRetorno := IcmpSendEcho(
HNDFile,
Endereco^,
null,
0,
Ip,
Icmp,
sizeof(Icmp),
DWORD(5000));
Destino.S_addr := icmp.source;
Memo1.Lines.Add('Pingou ' + Edit1.text);
end;


IcmpCLoseHandle(HNDFile);
FreeLibrary(HNDicmp);
WSACleanup();
end;

end.

 
楼上的GG

我的英语不是很好

不是很看的懂,能帮我翻译一下吗?
 
调用icmp.dll (win自带的)

function IcmpCreateFile():THandle;stdcall external 'ICMP.dll';
function IcmpCloseHandle(Handle:THandle):Boolean;stdcall external 'ICMP.dll';
function IcmpSendEcho(Handle:THandle;DestAddr:DWORD;
RequestData: Pointer;RequestSize: Word;RequestOptions: PIPOptionInformation;
ReplyBuffer: Pointer;ReplySize: DWORD;Timeout: DWORD): DWORD;stdcall external 'ICMP.dll';
function ValidCheck():THandle;
procedure FreeWinsock(hWnd:THandle);
function Ping(hICMP:THandle;IPAddr:String;TimeOut:Word):String;
看不懂的话,,留下信箱,给你个简单的例子

http://ozcbb.com/temp/ping.zip
 
ICS控件包中有一个Ping控件,很好用的
用google搜一下;
本人程序中的一段:
//检测本机到指定的DCOM服务器之间的网络是否连通
PingDcomServer.Address := DCOMServer;
PingDcomServer.Size:=32;
PingDcomServer.Timeout:=500;
PingDcomServer.Ping;
Application.ProcessMessages;
if PingDcomServer.ErrorCode=0 then
begin //如果本机到指定服务器之间的网络处于连通状态
//连接DCOM服务
 
找个简单的吧!
你看看
首先,对编程中需要的动态链接库作一简要说明:在Windows的System目录下,你
可以找到Icmp.dll文件,该动态链接库提供了ICMP协议的所有功能,我们的编程就建立
在对该动态链接库的调用上。

  Icmp.dll文件内的调用函数说明如下:

  1、IcmpCreateFile

  打开一个句柄,通过该句柄你可以发送ICMP的请求回送报文。

  2、IcmpCloseHandle

  关闭你通过IcmpCreateFile函数打开的句柄。

  3、IcmpSendEcho

  通过你打开的句柄发送ICMP请求,在超时或应答报文接收后返回。其参数基本上和
它的帧结构一致,可参看下面的程序部分,其具体含意你可以参看有关ICMP协议的书
籍。

    type
   PIPOptionInformation = ^TIPOptionInformation;
   TIPOptionInformation = packed record
   TTL: Byte;
   TOS: Byte;
   Flags: Byte;
   OptionsSize: Byte;
   OptionsData: PChar;
   end;
   PIcmpEchoReply = ^TIcmpEchoReply;
   TIcmpEchoReply = packed record
   Address: DWORD;
   Status: DWORD;
   RTT: DWORD;
   DataSize: Word;
   Reserved: Word;
   Data: Pointer;
   Options: TIPOptionInformation;
   end;
   TIcmpCreateFile = function: THandle; stdcall;
   TIcmpCloseHandle = function(IcmpHandle: THandle): Boolean;
stdcall;
   TIcmpSendEcho = function(IcmpHandle:THandle;
   DestinationAddress: DWORD;
   RequestData: Pointer;
   RequestSize: Word;
   RequestOptions: PIPOptionInformation;
   ReplyBuffer: Pointer;
   ReplySize: DWord;
   Timeout: DWord
   ): DWord; stdcall;
   TMyPing = class(TForm)
   Panel1: TPanel;
   Label1: TLabel;
   PingEdit: TEdit;
   ExeBtn: TButton;
   Button2: TButton;
   Button3: TButton;
   StatusShow: TMemo;
   procedure Button3Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure ExeBtnClick(Sender: TObject);
   private
   { Private declarations }
   hICMP: THANDLE;
   IcmpCreateFile : TIcmpCreateFile;
   IcmpCloseHandle: TIcmpCloseHandle;
   IcmpSendEcho: TIcmpSendEcho;
   public
   { Public declarations }
  end;
  procedure TMyPing.FormCreate(Sender: TObject);
  var
   WSAData: TWSAData;
   hICMPdll: HMODULE;
  begin
   // Load the icmp.dll stuff
   hICMPdll := LoadLibrary('icmp.dll');
   @ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile');
   @IcmpCloseHandle := GetProcAddress(hICMPdll,
'IcmpCloseHandle');
   @IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho');
   hICMP := IcmpCreateFile;
   StatusShow.Text := '';
   StatusShow.Lines.Add('目的IP地址 字节数 返回时间(毫秒)');
  end;

// 接下来,就要进行如下所示的Ping操作的实际编程过程了。

  procedure TMyPing.ExeBtnClick(Sender: TObject);
  var
   IPOpt:TIPOptionInformation;// IP Options for packet to send
   FIPAddress:DWORD;
   pReqData,pRevData:PChar;
   pIPE:PIcmpEchoReply;// ICMP Echo reply buffer
   FSize: DWORD;
   MyString:string;
   FTimeOut:DWORD;
   BufferSize:DWORD;
  begin
   if PingEdit.Text <> '' then
   begin
   FIPAddress := inet_addr(PChar(PingEdit.Text));
   FSize := 40;
   BufferSize := SizeOf(TICMPEchoReply) + FSize;
   GetMem(pRevData,FSize);
   GetMem(pIPE,BufferSize);
   FillChar(pIPE^, SizeOf(pIPE^), 0);
   pIPE^.Data := pRevData;
   MyString := 'Hello,World';
   pReqData := PChar(MyString);
   FillChar(IPOpt, Sizeof(IPOpt), 0);
   IPOpt.TTL := 64;
   FTimeOut := 4000;
   IcmpSendEcho(hICMP, FIPAddress, pReqData, Length(MyString),
@IPOpt, pIPE, BufferSize, FTimeOut);
   if pReqData^ = pIPE^.Options.OptionsData^ then
   begin
   StatusShow.Lines.Add(PChar(PingEdit.Text) + ' '
+IntToStr(pIPE^.DataSize) + ' ' +IntToStr(pIPE^.RTT));
   end;
   begin
   StatusShow.Lines.Add(PChar(PingEdit.Text) + ' '
+IntToStr(pIPE^.DataSize) + ' ' +IntToStr(pIPE^.RTT));
   end;
   FreeMem(pRevData);
   FreeMem(pIPE);
   end
  end;
 // 通过上面的编程,我们就实现了Ping功能的界面操作。
 
天啊,出去了一下,回来就看见连源代码带下载例子什么都有了。
各位好快的手!我都没东西贴了
 
谢谢几位GG了

不过小妹还想知道

如果PING通之后我还想执行一个EXE文件

该怎么做呢?
 
检查超时或应答报文的信息,决定是否执行程序
调用如 winexec('notepad.exe',1) 来执行程序!
 
写成Bat文件执行,最方便。
TFileStream
 
winexec('ping HostName >c:/result.txt',sw_Hide);

然后Memo1.Lines.LoadFromFile('c:/result.txt');

执行exe还用winexec好了。
 
好详细啊[:D],学习
 
多人接受答案了。
 
后退
顶部