求救,用rawsocket做ping的代码,采用select 设置超时小于1秒不成功(只有这么多分了)(50分)

  • 主题发起人 tanafenga
  • 开始时间
T

tanafenga

Unregistered / Unconfirmed
GUEST, unregistred user!
用rawsocket做ping的代码,采用select 设置超时小于1秒不成功
当 timeval.tv_sec >0的时候,功能正常
我想设置为毫秒级时就不成功
timeval.tv_sec=0
timeval.tv_usec=500;不论多大,全部都为超时
不知道哪为大侠知道答案。
主要代码如下:

procedure TForm1.Button2Click(Sender: TObject);
var
rawsock : TSocket;
ret : s32;
DestAdr,
FromAdr : TSockAddr;
pDestIP,
pIcmpHdr : PICMPHeader;
pRecvBuf : Pchar;
DataSize : u16;
fd_read : TFDSet;
timeval : TTimeVal;
fromlen : s32;
tick : u32;
pHost : PHostEnt;
MacName,sip :string;
begin

//创建一个RAW SOCKET,这是必须的,否则我们是无法分析IP包的~~~~~
rawsock := socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );
if rawsock = INVALID_Socket then

begin

ErrMsg( 'socket failed.');
exit;
end;

pIcmpHdr := AllocMem( MAX_PACKET_SIZE );
pRecvBuf := AllocMem( MAX_PACKET_SIZE );
DataSize := sizeof(YICMPHeader);
//填充ICMP头
FillICMPData( pIcmpHdr, MAX_PACKET_SIZE );
//计算校验和
pIcmpHdr^.u16chksum := 0;
pIcmpHdr^.u16chksum := CheckSum( PU16(pIcmpHdr), DataSize );
tick := GetTickCount();
FillChar( DestAdr, sizeof(DestAdr), 0 );
DestAdr.sin_family := AF_INET;
sip:=edit1.Text;
DestAdr.sin_addr.S_addr := inet_addr( PChar(Edit1.Text) );
//如果edit1.text不是IP地址,而是域名
if DestAdr.sin_addr.S_addr = INADDR_NONE then
begin

pHost := gethostbyname( PChar(Edit1.Text) );
if pHost <> nil then

begin

move( pHost^.h_addr^^, DestAdr.sin_addr, pHost^.h_length );
DestAdr.sin_family := pHost^.h_addrtype;
end else

begin

ListBox1.Items.Add( '解析域名: ' + Edit1.Text + '出错。' );
closesocket(rawsock);
FreeMem( picmphdr );
FreeMem( precvbuf );
exit;
end;

end;

ListBox1.Items.Add( 'Ping ' + Edit1.Text + '......' );
Listbox1.Update;
//发送ICMP包
ret := sendto( rawsock, pIcmpHdr^, DataSize, 0, DestAdr, sizeof(DestAdr) );
if ret = socket_error then

begin

ErrMsg( 'sendto failed.' );
closesocket( rawsock );
FreeMem( pIcmpHdr );
FreeMem( pRecvBuf );
exit;
end;
FD_ZERO( fd_read );
FD_SET( rawsock, fd_read );
[red] timeval.tv_sec := 1;
timeval.tv_usec := 0;
//接收ICMP回复包
if select( 0, @fd_read, nil, nil, @timeval ) > 0 then
[/red] begin

if FD_ISSET( rawsock, fd_read ) then

begin
FillChar( FromAdr, sizeof(FromAdr), 0 );
FromAdr.sin_family := AF_INET;
FromLen := sizeof(FromAdr );
recvfrom( rawsock, pRecvBuf^, MAX_PACKET_SIZE, 0, FromAdr, FromLen );
ListBox1.Items.Add( DecodeIcmpReply2( pRecvBuf, tick ) );
end;
end else

begin

ListBox1.Items.Add( '超时。' );
end;
closesocket(rawsock);
FreeMem( pIcmpHdr );
FreeMem( pRecvBuf );
end;
 
已经解决
 
顶部