我有一个多线程的PING的程序,
//================================================================
//
//
// 对一个IP列表进行监控的线程
// sunhuiNO1@hotmail.com
//
//================================================================
unit SpyThread;
interface
uses
Classes,Windows,Messages,Winsock,Ping;
const WM_NOTIFYMSG=WM_USER+$100;
WM_ONLINE=WM_USER+$101;
WM_OULINE=WM_USER+$102;
WM_END=WM_USER+$103;
SPYCOUNT=20;
type
TIPtype=record
onLine:boolean;
count:integer;
end;
TSpyIP = class(TThread)
private
{ Private declarations }
FHandle:THandle;
FIPlist:TStringList;
FDelayTime:integer;
FPort:integer;
FNextTime:integer;
protected
procedure Execute; override;
public
property IPlist:TStringList write FIPlist;
property DelayTime:integer write FDelayTime default 2000;
property Port:integer write FPort;
property NextTime:integer write FNextTime default 10000;
constructor SpyIP(Handle:THandle);
destructor Destroy;override;
end;
implementation
{ Important: Methods and properties of objects in VCL can only be used in a
method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TSpyIP.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
{ TSpyIP }
constructor TSpyIP.SpyIP(Handle:THandle);
begin
inherited Create(true);
FHandle:=Handle;
Freeonterminate:=true;
FDelayTime:=2000;
FNextTime:=10000;
end;
destructor TSpyIP.Destroy;
begin
PostMessage(FHandle,WM_END,0,0);
inherited destroy;
end;
procedure TSpyIP.Execute;
var
i,j:integer;
onLine:boolean;
ouLine:array[0..SPYCOUNT-1]of TIPtype;
begin
for i:=0 to SPYCOUNT-1 do
begin
ouLine
.onLine:=false;
ouLine.count:=0;
end;
if (FIPlist.Count=0) and (FIPlist.Count>20) then exit;
while not Terminated do
begin
for i:=0 to FIPlist.Count-1 do
begin
if ouLine.onLine then
begin
inc(ouLine.count);
if ouLine.count<10 then
break
else
ouLine.count:=0;
end;
onLine:=PingServer(FIPlist.Strings,FDelayTime);
if onLine then //如果能PING通
begin
if not ouLine.onLine then
PostMessage(FHandle,WM_ONLINE,i,0);
ouLine.onLine:=true;
ouLine.count:=0;
end
else //如果不能PING通
begin
if ouLine.onLine then //如果该机开始是在线
begin
PostMessage(FHandle,WM_OULINE,i,0);
ouLine.onLine:=false;
ouLine.count:=0;
end;
end;
end;
Sleep(FNextTime);
end;
end;
end.
unit Ping;
interface
uses
Windows,Winsock,Sysutils;
Const
{ Exception Message }
SInitFailed = 'Winsock version error';
SInvalidAddr = 'Invalid IP Address';
SNoResponse = 'No Response';
STimeOut = 'Request TimeOut';
type
DWORD=LongWord;
THandle=LongWord;
PIPOptionInformation = ^TIPOptionInformation;
TIPOptionInformation = record
TTL: Byte;
TOS: Byte;
Flags: Byte;
OptionsSize: Byte;
OptionsData: PChar;
end;
PIcmpEchoReply = ^TIcmpEchoReply;
TIcmpEchoReply =
record
Address: DWORD;
Status: DWORD;
RTT: DWORD;
DataSize:Word;
Reserved: Word;
Data: Pointer;
Options: TIPOptionInformation;
end;
function IcmpCreateFile():THandle;stdcall external 'ICMP.dll';
function IcmpCloseHandle(Handle:THandle):Boolean;stdcall external 'ICMP.dll';
function IcmpSendEcho(Handle:THandle;
DestAddrWORD;
RequestData: Pointer;
RequestSize: Word;
RequestOptions: PIPOptionInformation;
ReplyBuffer: Pointer;
ReplySize: DWORD;
Timeout: DWORD): DWORD;stdcall external 'ICMP.dll';
procedure ValidCheck();
procedure FreeWinsock();
function PingServer(IPAddr:String;TimeOut:Word):boolean;
var
hICMP:THandle;
implementation
procedure ValidCheck();
var
WSAData:TWSAData;
begin
if (WSAStartup($202,WSAData)<>0) then
raise Exception.Create(SInitFailed);
hIcmp:=IcmpCreateFile();
if hICMP=INVALID_HANDLE_VALUE then
raise Exception.Create('Create ICMP Failed');
end;
procedure FreeWinsock();
begin
IcmpCloseHandle(hIcmp);
WSACleanUP;
end;
function PingServer(IPAddr:String;TimeOut:Word):boolean;
var
IPOpt:TIPOptionInformation;// IP Options for packet to send
FIPAddressWORD;
pReqData,pRevDataChar;
pIPEIcmpEchoReply;// ICMP Echo reply buffer
FSize: DWORD;
MyString:string;
FTimeOutWORD;
BufferSizeWORD;
temp:Integer;
pIPAddrchar;
begin
GetMem(pIPAddr,Length(IPAddr)+1);
FillChar(pIPAddr^,Length(IPAddr)+1,0);
StrPCopy(pIPAddr,IPAddr);
FIPAddress := inet_addr(pIPAddr);
FreeMem(pIPAddr);
if FIPAddress=INADDR_NONE then
begin
result:=false;//Exit
exit;
end;
FSize := 40;
BufferSize := SizeOf(TICMPEchoReply) + FSize;
GetMem(pRevData,FSize);
GetMem(pIPE,BufferSize);
FillChar(pIPE^, SizeOf(pIPE^), 0);
pIPE^.Data := pRevData;
MyString := 'Ping Digital Data';
pReqData := PChar(MyString);
FillChar(IPOpt, Sizeof(IPOpt), 0);
IPOpt.TTL := 64;
//time out
FTimeOut := TimeOut;
//go!!!
temp:=IcmpSendEcho(hICMP,//dll handle
FIPAddress,//target
pReqData,//data
Length(MyString),//data length
@IPOpt,//addree of ping option
pIPE,//
BufferSize,//pack size
FTimeOut);//timeout value
if temp=0 then
begin
Result:=false;
exit;
end;
if pReqData^ = pIPE^.Options.OptionsData^ then
Result:=true
else
Result:=false;
FreeMem(pRevData);
FreeMem(pIPE);
end;
end.