我写了一个PING程序,使用的是ICMP,UDP,但是sendto()发送的数据,在recvfrom()收到的时候却完全不一样,也可以说是没有收到,这个问题折磨我一下午,望各位给小弟指点迷津,谢谢!  代码有点长可能要分两次贴上,望各位见谅。
  环境:windows 2000 server +sp3
      vc++ 6.0 
///////////////////
//Ping.cpp
//使用ICMP 和RAW Socket
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>#include "ping.h"
void Ping(LPCSTR lpszHost);
void ReportError(LPCSTR lpszFrom);
int  WaitForEchoReply(SOCKET s);
USHORT in_cksum(USHORT *addr, int len);//ICMP ECHO REQUEST/REPLY FUNCTIONS
int SendEchoRequest(SOCKET s, LPSOCKADDR_IN lpsToAddr);
DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsFrom, UCHAR *pTTL);
void main(int argc, char *argv[])
{
//检验参数
if(argc !=2 )
{
fprintf(stderr,"\nSytnax:ping hostname\n");
return;
}
//初始化winsock
int nRet;
WSADATA wsa;
nRet = WSAStartup(MAKEWORD(1,1), &wsa);
if(nRet)
{
fprintf(stderr,"\nError initializing winsock\n");
return;
} //工作函数
Ping(argv[1]);
//释放winsock
WSACleanup();
}//Ping()--主工作函数,显示运行结果
//
void Ping(LPCSTR lpszHost)
{
//建立socket
SOCKET rawSocket;
int nRet; rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(rawSocket == INVALID_SOCKET)
{
ReportError("socket()");
return;
}
//地址解析
IN_ADDR iaHost;
LPHOSTENT lpHostEntry;

iaHost.s_addr = inet_addr(lpszHost);
if(iaHost.s_addr == INADDR_NONE)
{
//是主机名
lpHostEntry = gethostbyname(lpszHost);
}
else
{
//是IP地址
lpHostEntry = gethostbyaddr((const char *)&iaHost,
sizeof(IN_ADDR), AF_INET);
}
if(lpHostEntry == NULL)
{
fprintf(stderr,"\nHost not found: %s\n", lpszHost);
return;
}


//填充目标地址结构
SOCKADDR_IN saDest;
saDest.sin_addr.s_addr = *((u_long FAR *)lpHostEntry->h_addr);
saDest.sin_family = AF_INET;
saDest.sin_port   = 0; //显示信息
printf("\nPinging %s [%s] with %d bytes of data:\n",
lpszHost, inet_ntoa(saDest.sin_addr),
REQ_DATASIZE); ///////////////////////////////////////
//核心代码Ping 4次
///////////////////////////////////////
DWORD dwTimeSent;
DWORD dwElapsed;
SOCKADDR_IN saSrc;
UCHAR cTTL;
for(int nLoop = 0; nLoop < 4; nLoop++)
{
//发关ICMP回应请求(ICMP echo request)
SendEchoRequest(rawSocket, &saDest); //等待数据返回
nRet = WaitForEchoReply(rawSocket);
if(nRet == SOCKET_ERROR)
{
ReportError("select()");
break;
}
if(!nRet)
{
printf("\nTimeOut");
break;
} //收到回应
dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL);
//计算已用时间
dwElapsed = GetTickCount() - dwTimeSent;
//test
printf("\n GetTickcount() = %ld  dwTimeSent = %ld", 
GetTickCount(), dwTimeSent);
//
printf("\nReply from: %s: bytes=%d time=%ldms TTL=%d",
inet_ntoa(saSrc.sin_addr), REQ_DATASIZE,
dwElapsed, cTTL);
}

printf("\n");
shutdown(rawSocket, 2);
closesocket(rawSocket);
}
//SendEchoRequest()
//填充echo request header,发送到目标主机
//
int SendEchoRequest(SOCKET s, LPSOCKADDR_IN lpsToAddr)
{
static ECHOREQUEST echoReq;
static int nId = 1;
static int nSeq= 1; //填充回应请求(echo request)
echoReq.icmpHdr.TYPE = ICMP_ECHOREQ;
echoReq.icmpHdr.CODE = 0;
echoReq.icmpHdr.CHECKSUM = 0;
echoReq.icmpHdr.ID = nId++;
echoReq.icmpHdr.SEQ = nSeq++; for(int i = 0; i < REQ_DATASIZE; i++)
{
echoReq.chData[i] = ' ' + i;
}
echoReq.dwTime = GetTickCount(); echoReq.icmpHdr.CHECKSUM = in_cksum((USHORT *)&echoReq, 
sizeof(ECHOREQUEST));

//发送回应请求
int nRet; nRet = sendto(s, 
  (LPSTR)&echoReq, 
  sizeof(ECHOREQUEST),
  0,
  (LPSOCKADDR)lpsToAddr,
  sizeof(SOCKADDR_IN));
//test
printf("\n sendto echoReq.dwTime = %ld \n", echoReq.dwTime);
//
if(nRet == SOCKET_ERROR)
{
ReportError("sendto()");
} return (nRet);
}
//RecvEchoReply()
//返回数据信息
//
DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsFrom, UCHAR *pTTL)
{
ECHOREPLY echoReply;
int nRet;
int nLen = sizeof(SOCKADDR_IN); //收到echo回应
nRet = recvfrom(s, 
(LPSTR)&echoReply, 
sizeof(ECHOREPLY), 
0,
(LPSOCKADDR)lpsFrom,
&nLen);
//test
printf("\n recvfrom echoReply.echoRequest.dwTime = %ld \n", echoReply.echoRequest.dwTime);
//
if(nRet == SOCKET_ERROR)
{
ReportError("recvfrom()");
} //返回发送时间和IP TTL
*pTTL = echoReply.ipHdr.TTL;
return(echoReply.echoRequest.dwTime);
}//ReportError()
//显示错误信息
//
void ReportError(LPCSTR lpszFrom)
{
fprintf(stderr, "\n%s error: %d\n", lpszFrom, WSAGetLastError());
}//WaitForEchoReply()
//用select()确定什么时间数据等待读
//
int WaitForEchoReply(SOCKET s)
{
FD_SET readfds; readfds.fd_count = 1;
readfds.fd_array[0] = s; static TIMEVAL Timeout; Timeout.tv_sec = 5;
Timeout.tv_usec = 0; return(select(1, &readfds, NULL, NULL, &Timeout));
}
//in_cksum()
//
USHORT in_cksum(USHORT *addr, int len)
{
register int nleft = len;
register USHORT *w   = addr;
register USHORT answer;
register int sum   = 0;
while(nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if(nleft ==1)
{
USHORT u = 0; *(UCHAR *)(&u) = *(UCHAR *)w;
sum += u;
} sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}