H
HUAGUAN
Unregistered / Unconfirmed
GUEST, unregistred user!
这是我从C翻译过来的,为什么C可以运行而下面的程序一运行到recvfrom就超时
unit Uping;
interface
uses Windows, SysUtils, winsock;
const
SOCKET_ERROR = -1;
ICMP_ECHO = 8;
ICMP_MIN = 8;
ICMP_ECHOREPLY = 0;
MAX_IP_HDR_SIZE = 60;
MAX_PACKET = 1024;
SOL_SOCKET = $FFFF;
SOMAXCONN = $7FFFFFFF;
WSA_FLAG_OVERLAPPED = $1;
MAX_PROTOCOL_CHAIN = 7;
WSAPROTOCOL_LEN = 255;
IP_RECORD_ROUTE = $07;
type
WSAPROTOCOLCHAIN = record
ChainLen: Integer;
ChainEntries: array[0..MAX_PROTOCOL_CHAIN - 1] of DWORD;
end;
TWSAData = record
wVersion: WORD;
wHighVersion: WORD;
szDescription: array[0..WSADESCRIPTION_LEN] of Char;
szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
iMaxSockets: Word;
iMaxUdpDg: Word;
lpVendorInfo: PChar;
end;
PWSAPROTOCOL_INFO = ^WSAPROTOCOL_INFO;
WSAPROTOCOL_INFO = record
dwServiceFlags1: DWORD;
dwServiceFlags2: DWORD;
dwServiceFlags3: DWORD;
dwServiceFlags4: DWORD;
dwProviderFlags: DWORD;
ProviderId: TGUID;
dwCatalogEntryId: DWORD;
ProtocolChain: WSAPROTOCOLCHAIN;
iVersion: Integer;
iAddressFamily: Integer;
iMaxSockAddr: Integer;
iMinSockAddr: Integer;
iSocketType: Integer;
iProtocol: Integer;
iProtocolMaxOffset: Integer;
iNetworkByteOrder: Integer;
iSecurityScheme: Integer;
dwMessageSize: DWORD;
dwProviderReserved: DWORD;
szProtocol: array[0..WSAPROTOCOL_LEN] of WideChar;
end;
PIpOptionHeader = ^TIpOptionHeader;
TIpOptionHeader = record
code: Byte;
len: Byte;
ptr: Byte;
addr: array[0..8] of ULONG; // List of IP addrs
end;
PIpHeader = ^TIpHeader;
TIpHeader = record
h_len: DWORD;
version: DWORD;
tos: Byte;
total_len: Word;
ident: Word;
FragAndFlags: Word;
ttl: Byte;
proto: Byte;
checksum: Word;
sourceIP: DWORD;
destIP: DWORD;
end;
PIcmpHeader = ^TIcmpHeader;
TIcmpHeader = record
i_type: Byte;
i_code: Byte;
i_cksum: Word;
i_id: Word;
i_seq: Word;
timestamp: ULONG;
end;
TPacketBuffer = array[0..Max_Packet - 1] of byte;
function WSASocket(af, type_, protocol: Integer; lpProtocolInfo: PWSAPROTOCOL_INFO;
g: Cardinal; dwFlags: DWORD): TSocket; stdcall;
function setsockopt(s: TSocket; level, optname: Integer; optval: PChar; optlen: Integer): Integer; stdcall;
function WSAGetLastError: Integer; stdcall;
procedure Ping;
implementation
function WSASocket; external 'ws2_32.dll' name 'WSASocketW';
function setsockopt; external 'ws2_32.dll' name 'setsockopt';
function WSAGetLastError; external 'ws2_32.dll' name 'WSAGetLastError';
function MAKEWORD(low, high: Word): Word;
begin
Result := low or (high shr 8);
end;
function CreateSock: TSocket;
var wsData: WSAData;
begin
if (WSAStartup(MAKEWORD(2, 2), wsData) = 0) then
Result := WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, nil, 0,
WSA_FLAG_OVERLAPPED)
else Result := INVALID_SOCKET;
end;
procedure DestraySock(ASK: TSocket);
begin
if ASK <> INVALID_SOCKET then closesocket(ASK);
WSACleanup;
end;
procedure FillICMPData(icmp_data: PChar; datasize: Integer);
var
icmp_hdr: PIcmpHeader;
datapart: PChar;
begin
icmp_hdr := PIcmpHeader(icmp_data);
icmp_hdr^.i_type := ICMP_ECHO;
icmp_hdr^.i_code := 0;
icmp_hdr^.i_id := Word(GetCurrentProcessId());
icmp_hdr^.i_cksum := 0;
icmp_hdr^.i_seq := 0;
datapart := icmp_data + sizeof(TIcmpHeader);
FillChar(datapart^, datasize - sizeof(TIcmpHeader), 'E');
end;
function checksum(var buffer; size: Integer): Word;
var cksum: LongWord;
i: Integer;
P: PChar;
begin
cksum := 0;
p := @buffer;
for i := 0 to size - 1 do
cksum := cksum + word((p + i)^);
if (size mod 2) = 1 then cksum := cksum + byte((P + size)^);
cksum := (cksum shr 16) + (cksum and $FFFF);
cksum := cksum + (cksum shr 16);
Result := word(cksum);
end;
procedure DecodeIPOptions(buf: PChar; bytes: Integer);
var
ipopt: PIpOptionHeader;
inaddr: TInAddr;
i: Integer;
host: Phostent;
begin
end;
procedure DecodeICMPHeader(buf: PChar; bytes: Integer; from: PSockAddrIn);
var
iphdr: PIpHeader;
icmphdr: PIcmpHeader;
iphdrlen: Word;
tick: DWORD;
icmpcount: Integer;
begin
end;
procedure Ping;
var SK: TSocket;
M_ipopt: TIpOptionHeader;
TimeOut: Integer;
SouIp, DestIp: TSockAddrIn;
DataSize, bwrote, FromLen: Integer;
seq_no: Word;
icmp_data, recvbuf: TPacketBuffer;
begin
SK := CreateSock;
if SK = INVALID_SOCKET then Exit;
{ M_ipopt.code := IP_RECORD_ROUTE;
M_ipopt.len :=39;
M_ipopt.ptr := 4;
bwrote := setsockopt(SK, IPPROTO_IP, IP_OPTIONS, PChar(@M_ipopt), sizeof(M_ipopt));
if bwrote = SOCKET_ERROR then Exit;
//设置记录路由 }
TimeOut := 1000;
if setsockopt(SK, SOL_SOCKET, SO_RCVTIMEO, PChar(@TimeOut), sizeof(TimeOut)) = SOCKET_ERROR then Exit;
//设置接收超时
if setsockopt(SK, SOL_SOCKET, SO_SNDTIMEO, PChar(@TimeOut), sizeof(TimeOut)) = SOCKET_ERROR then Exit;
//设置发送超时
DestIp.sin_family := AF_INET;
DestIp.sin_addr.S_addr := inet_addr('192.168.1.28');
DataSize := 23 + sizeof(TIcmpHeader);
seq_no := 0;
FillChar(icmp_data, MAX_PACKET, 0);
FillICMPData(@icmp_data, datasize);
inc(seq_no);
PIcmpHeader(@icmp_data).timestamp := GetTickCount();
PIcmpHeader(@icmp_data).i_seq := seq_no;
PIcmpHeader(@icmp_data).i_cksum := checksum(icmp_data, datasize);
bwrote := sendto(SK, icmp_data, DataSize, 0, DestIp, sizeof(DestIp));
if bwrote = SOCKET_ERROR then
begin
raise Exception.Create(format('%d', [WSAGetLastError]));
Exit;
end;
FromLen := sizeof(SouIp);
while true do
begin
bwrote := recvfrom(SK, recvbuf, MAX_PACKET, 0, SouIp, FromLen);
if (bwrote = SOCKET_ERROR) then
if (WSAGetLastError() = WSAETIMEDOUT) then continue
else
begin
raise Exception.Create(format('%d', [WSAGetLastError]));
Exit;
end;
end;
DestraySock(SK);
end;
end.
unit Uping;
interface
uses Windows, SysUtils, winsock;
const
SOCKET_ERROR = -1;
ICMP_ECHO = 8;
ICMP_MIN = 8;
ICMP_ECHOREPLY = 0;
MAX_IP_HDR_SIZE = 60;
MAX_PACKET = 1024;
SOL_SOCKET = $FFFF;
SOMAXCONN = $7FFFFFFF;
WSA_FLAG_OVERLAPPED = $1;
MAX_PROTOCOL_CHAIN = 7;
WSAPROTOCOL_LEN = 255;
IP_RECORD_ROUTE = $07;
type
WSAPROTOCOLCHAIN = record
ChainLen: Integer;
ChainEntries: array[0..MAX_PROTOCOL_CHAIN - 1] of DWORD;
end;
TWSAData = record
wVersion: WORD;
wHighVersion: WORD;
szDescription: array[0..WSADESCRIPTION_LEN] of Char;
szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
iMaxSockets: Word;
iMaxUdpDg: Word;
lpVendorInfo: PChar;
end;
PWSAPROTOCOL_INFO = ^WSAPROTOCOL_INFO;
WSAPROTOCOL_INFO = record
dwServiceFlags1: DWORD;
dwServiceFlags2: DWORD;
dwServiceFlags3: DWORD;
dwServiceFlags4: DWORD;
dwProviderFlags: DWORD;
ProviderId: TGUID;
dwCatalogEntryId: DWORD;
ProtocolChain: WSAPROTOCOLCHAIN;
iVersion: Integer;
iAddressFamily: Integer;
iMaxSockAddr: Integer;
iMinSockAddr: Integer;
iSocketType: Integer;
iProtocol: Integer;
iProtocolMaxOffset: Integer;
iNetworkByteOrder: Integer;
iSecurityScheme: Integer;
dwMessageSize: DWORD;
dwProviderReserved: DWORD;
szProtocol: array[0..WSAPROTOCOL_LEN] of WideChar;
end;
PIpOptionHeader = ^TIpOptionHeader;
TIpOptionHeader = record
code: Byte;
len: Byte;
ptr: Byte;
addr: array[0..8] of ULONG; // List of IP addrs
end;
PIpHeader = ^TIpHeader;
TIpHeader = record
h_len: DWORD;
version: DWORD;
tos: Byte;
total_len: Word;
ident: Word;
FragAndFlags: Word;
ttl: Byte;
proto: Byte;
checksum: Word;
sourceIP: DWORD;
destIP: DWORD;
end;
PIcmpHeader = ^TIcmpHeader;
TIcmpHeader = record
i_type: Byte;
i_code: Byte;
i_cksum: Word;
i_id: Word;
i_seq: Word;
timestamp: ULONG;
end;
TPacketBuffer = array[0..Max_Packet - 1] of byte;
function WSASocket(af, type_, protocol: Integer; lpProtocolInfo: PWSAPROTOCOL_INFO;
g: Cardinal; dwFlags: DWORD): TSocket; stdcall;
function setsockopt(s: TSocket; level, optname: Integer; optval: PChar; optlen: Integer): Integer; stdcall;
function WSAGetLastError: Integer; stdcall;
procedure Ping;
implementation
function WSASocket; external 'ws2_32.dll' name 'WSASocketW';
function setsockopt; external 'ws2_32.dll' name 'setsockopt';
function WSAGetLastError; external 'ws2_32.dll' name 'WSAGetLastError';
function MAKEWORD(low, high: Word): Word;
begin
Result := low or (high shr 8);
end;
function CreateSock: TSocket;
var wsData: WSAData;
begin
if (WSAStartup(MAKEWORD(2, 2), wsData) = 0) then
Result := WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, nil, 0,
WSA_FLAG_OVERLAPPED)
else Result := INVALID_SOCKET;
end;
procedure DestraySock(ASK: TSocket);
begin
if ASK <> INVALID_SOCKET then closesocket(ASK);
WSACleanup;
end;
procedure FillICMPData(icmp_data: PChar; datasize: Integer);
var
icmp_hdr: PIcmpHeader;
datapart: PChar;
begin
icmp_hdr := PIcmpHeader(icmp_data);
icmp_hdr^.i_type := ICMP_ECHO;
icmp_hdr^.i_code := 0;
icmp_hdr^.i_id := Word(GetCurrentProcessId());
icmp_hdr^.i_cksum := 0;
icmp_hdr^.i_seq := 0;
datapart := icmp_data + sizeof(TIcmpHeader);
FillChar(datapart^, datasize - sizeof(TIcmpHeader), 'E');
end;
function checksum(var buffer; size: Integer): Word;
var cksum: LongWord;
i: Integer;
P: PChar;
begin
cksum := 0;
p := @buffer;
for i := 0 to size - 1 do
cksum := cksum + word((p + i)^);
if (size mod 2) = 1 then cksum := cksum + byte((P + size)^);
cksum := (cksum shr 16) + (cksum and $FFFF);
cksum := cksum + (cksum shr 16);
Result := word(cksum);
end;
procedure DecodeIPOptions(buf: PChar; bytes: Integer);
var
ipopt: PIpOptionHeader;
inaddr: TInAddr;
i: Integer;
host: Phostent;
begin
end;
procedure DecodeICMPHeader(buf: PChar; bytes: Integer; from: PSockAddrIn);
var
iphdr: PIpHeader;
icmphdr: PIcmpHeader;
iphdrlen: Word;
tick: DWORD;
icmpcount: Integer;
begin
end;
procedure Ping;
var SK: TSocket;
M_ipopt: TIpOptionHeader;
TimeOut: Integer;
SouIp, DestIp: TSockAddrIn;
DataSize, bwrote, FromLen: Integer;
seq_no: Word;
icmp_data, recvbuf: TPacketBuffer;
begin
SK := CreateSock;
if SK = INVALID_SOCKET then Exit;
{ M_ipopt.code := IP_RECORD_ROUTE;
M_ipopt.len :=39;
M_ipopt.ptr := 4;
bwrote := setsockopt(SK, IPPROTO_IP, IP_OPTIONS, PChar(@M_ipopt), sizeof(M_ipopt));
if bwrote = SOCKET_ERROR then Exit;
//设置记录路由 }
TimeOut := 1000;
if setsockopt(SK, SOL_SOCKET, SO_RCVTIMEO, PChar(@TimeOut), sizeof(TimeOut)) = SOCKET_ERROR then Exit;
//设置接收超时
if setsockopt(SK, SOL_SOCKET, SO_SNDTIMEO, PChar(@TimeOut), sizeof(TimeOut)) = SOCKET_ERROR then Exit;
//设置发送超时
DestIp.sin_family := AF_INET;
DestIp.sin_addr.S_addr := inet_addr('192.168.1.28');
DataSize := 23 + sizeof(TIcmpHeader);
seq_no := 0;
FillChar(icmp_data, MAX_PACKET, 0);
FillICMPData(@icmp_data, datasize);
inc(seq_no);
PIcmpHeader(@icmp_data).timestamp := GetTickCount();
PIcmpHeader(@icmp_data).i_seq := seq_no;
PIcmpHeader(@icmp_data).i_cksum := checksum(icmp_data, datasize);
bwrote := sendto(SK, icmp_data, DataSize, 0, DestIp, sizeof(DestIp));
if bwrote = SOCKET_ERROR then
begin
raise Exception.Create(format('%d', [WSAGetLastError]));
Exit;
end;
FromLen := sizeof(SouIp);
while true do
begin
bwrote := recvfrom(SK, recvbuf, MAX_PACKET, 0, SouIp, FromLen);
if (bwrote = SOCKET_ERROR) then
if (WSAGetLastError() = WSAETIMEDOUT) then continue
else
begin
raise Exception.Create(format('%d', [WSAGetLastError]));
Exit;
end;
end;
DestraySock(SK);
end;
end.