recvfrom ()总是返回-1
#define IP_RECORD_ROUTE 0x07
#define IP_OPTIONS 0x01
// ipheader struct...
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8 //Minimum 8-byte packet (header)
// icmp header struct
// IP option header use of socket with IP_OPTIONS
#define DEF_PACKET_SIZE 32 // default packet size
#define MAX_PACKET_SIZE 1024 // icmp header max length
#define MAX_IP_HDR_SIZE 60 // max ip header size w/options
BOOL bRecRoute;
int dataSize;
char *lpDest;
// function FillIcmpHeader()
// description
//
void FillIcmpHeader(char *icmp_data, int datasize)
{
IcmpHeader *icmp_hdr = NULL;
char *datapart = NULL;
icmp_hdr = (IcmpHeader*)icmp_data;
icmp_hdr->type = ICMP_ECHO;
icmp_hdr->code = 0;
icmp_hdr->ident = (unsigned short)GetCurrentProcessId();
icmp_hdr->checksum = 0;
icmp_hdr->seq = 0;
datapart = icmp_data + sizeof(IcmpHeader);
memset(datapart, 'E', datasize - sizeof(IcmpHeader));
}
// function CheckSum()
// description
//
USHORT CheckSum(USHORT *buffer, int datasize)
{
unsigned long cksum = 0;
while (datasize > 0)
{
cksum += *buffer++;
datasize -= sizeof(USHORT);
}
if (datasize != 0)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum && 0xFFFF);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
}
//...
//
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET sockRaw = INVALID_SOCKET;
struct sockaddr_in dest,
local,
from;
int bread,
fromlen = sizeof(from),
timeout = 1000,
ret;
char *icmp_data = NULL,
*recv_buf = NULL;
unsigned int addr = 0;
USHORT seq_no = 0;
struct hostent *hp = NULL;
IpOptionHeader ipopt;
ValidateArgs(argc, argv);
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("WSAStartup failed. %d\n", WSAGetLastError());
return -1;
}
if ((sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == INVALID_SOCKET)
//if ((sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed. %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (bRecRoute)
{
memset((void*)&ipopt, 0, sizeof(ipopt));
ipopt.code = IP_RECORD_ROUTE;
ipopt.ptr = 4;
ipopt.len = 39;
ret = setsockopt(sockRaw, IPPROTO_IP, IP_OPTIONS, (char*)&ipopt, sizeof(ipopt));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(IP_OPTIONS) failed. %d\n", WSAGetLastError());
}
}
ret = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(SO_RECVTIMEO) failed. %d\n", WSAGetLastError());
closesocket(sockRaw);
WSACleanup();
return -1;
}
timeout = 1000;
ret = setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(SO_SNDTIMEO) failed. %d\n", WSAGetLastError());
closesocket(sockRaw);
WSACleanup();
return -1;
}
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
if ((dest.sin_addr.S_un.S_addr = inet_addr(lpDest)) == INADDR_NONE)
{
if ((hp = gethostbyname(lpDest)) == NULL)
{
printf("gethostbyname() failed. %d\n", WSAGetLastError());
closesocket(sockRaw);
WSACleanup();
return -1;
}
else
{
memcpy(&(dest.sin_addr), hp->h_addr_list, hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("dest.sin_addr = %s\n", inet_ntoa(dest.sin_addr));
}
}
dataSize += sizeof(IcmpHeader);
icmp_data = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET_SIZE);
recv_buf = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET_SIZE);
if (icmp_data == NULL || recv_buf == NULL)
{
printf("HeapAlloc() failed. %d\n", GetLastError());
closesocket(sockRaw);
WSACleanup();
return -1;
}
FillIcmpHeader(icmp_data, dataSize);
local.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
local.sin_family = AF_INET;
/*
ret = bind(sockRaw, (sockaddr*)&local, sizeof(local));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(SO_SNDTIMEO) failed. %d\n", WSAGetLastError());
closesocket(sockRaw);
WSACleanup();
return -1;
}
*/
while (1)
{
static int nCount = 0;
int bwrote;
if (nCount ++ == 4)
{
break;
}
((IcmpHeader*)icmp_data)->checksum = 0;
((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
((IcmpHeader*)icmp_data)->seq = seq_no ++;
((IcmpHeader*)icmp_data)->checksum = CheckSum((USHORT*)icmp_data, dataSize);
bwrote = sendto(sockRaw, icmp_data, dataSize, 0, (sockaddr*)&dest, sizeof(sockaddr));
if (bwrote == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
printf("sendto time out\n");
continue;
}
printf("sendto() failed. %d\n", WSAGetLastError());
closesocket(sockRaw);
WSACleanup();
return -1;
}
if (bwrote < dataSize)
{
printf("wrote %d bytes\n", bwrote);
}
bread = recvfrom(sockRaw, recv_buf, MAX_PACKET_SIZE, 0, (sockaddr*)&from, &fromlen);
// 总是返回-1,请问为何?
if (bread == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
printf("recvfrom time out\n");
continue;
}
printf("recvfrom() failed. %d\n", WSAGetLastError());
closesocket(sockRaw);
WSACleanup();
return -1;
}
DecodeIcmpHeader(recv_buf, bread, &from);
Sleep(1000);
}
HeapFree(GetProcessHeap(), 0, recv_buf);
HeapFree(GetProcessHeap(), 0, icmp_data);
closesocket(sockRaw);
WSACleanup();
return 0;
}