【网络编程】之十三、ping程序实现

使用原始套接字:SOCK_RAW

需要ICMP

代码如下:

[cpp]  view plain copy
  1. #include  
  2. #include  
  3.   
  4. using namespace std;  
  5.   
  6. #pragma comment(lib, "WS2_32.lib")  
  7.   
  8. typedef struct icmp_hdr{  
  9.     unsigned char icmp_type;  
  10.     unsigned char icmp_code;  
  11.     unsigned short icmp_checksum;  
  12.     unsigned short icmp_id;  
  13.     unsigned short icmp_sequence;  
  14.     unsigned long icmp_timnestamp;  
  15. }ICMP_HDR, *PICMP_HDR;  
  16.   
  17.   
  18. typedef struct _IPHeader{  
  19.     UCHAR iphVerLen;  
  20.     UCHAR ipTOS;  
  21.     USHORT ipLength;  
  22.     USHORT ipID;  
  23.     USHORT ipFlags;  
  24.     UCHAR ipTTL;  
  25.     UCHAR ipProtocol;  
  26.     USHORT ipChecksum;  
  27.     ULONG ipSource;  
  28.     ULONG ipDestination;  
  29. }IPHeader, *PIPHeader;  
  30.   
  31. USHORT checksum(USHORT* buffer, int size)  
  32. {  
  33.     unsigned long cksum = 0;  
  34.   
  35.     while(size > 1)  
  36.     {  
  37.         cksum += *buffer++;  
  38.         size -= sizeof(USHORT);  
  39.     }  
  40.   
  41.     // 奇数,将最后一个字节扩展到双字, 再累加  
  42.     if(size)  
  43.         cksum += *(UCHAR*)buffer;  
  44.   
  45.     //高16  低16相加,取反  
  46.     cksum = (cksum >> 16) + (cksum & 0xffff);  
  47.     cksum += (cksum >> 16);  
  48.     return (USHORT)(~cksum);  
  49. }  
  50.   
  51. int main(void)  
  52. {  
  53.     char szDestIp[] = "127.0.0.1";  
  54.     SOCKET sRaw= ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);  
  55.     //SetTimeout(sRaw, 1000, TRUE);  
  56.   
  57.     SOCKADDR_IN dest;  
  58.     dest.sin_family = AF_INET;  
  59.     dest.sin_port = htons(5674);  
  60.     dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);  
  61.       
  62.     char buff[sizeof(ICMP_HDR) + 32];  
  63.     ICMP_HDR *pIcmp = (ICMP_HDR*)buff;  
  64.     pIcmp->icmp_type = 8;  
  65.     pIcmp->icmp_code = 0;  
  66.     pIcmp->icmp_id = (USHORT)::GetCurrentProcess();  
  67.     pIcmp->icmp_checksum = 0;  
  68.     pIcmp->icmp_sequence = 0;  
  69.     memset(&buff[sizeof(ICMP_HDR)], 'E', 32);  
  70.       
  71.     //发送  
  72.     USHORT nSeq = 0;  
  73.     char recvBuf[1024];  
  74.     SOCKADDR_IN from;  
  75.     int nLen = sizeof(from);  
  76.     while(TRUE)  
  77.     {  
  78.         static int nCount = 0;  
  79.         int nRet;  
  80.         if(nCount++ == 4)  
  81.             break;  
  82.         pIcmp->icmp_checksum = 0;  
  83.         pIcmp->icmp_timnestamp = ::GetTickCount();  
  84.         pIcmp->icmp_sequence = nSeq++;  
  85.         pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);  
  86.         nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR*)&dest, sizeof(dest));  
  87.         if(nRet == SOCKET_ERROR)  
  88.         {  
  89.             cout << "sendto error:" << ::WSAGetLastError() << endl;  
  90.             return -1;  
  91.         }  
  92.   
  93.         nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);  
  94.         if(nRet == SOCKET_ERROR)  
  95.         {  
  96.             if(::WSAGetLastError() == WSAETIMEDOUT)  
  97.             {  
  98.                 cout << "time out" << endl;  
  99.                 continue;  
  100.             }  
  101.             cout << "recvfrom failed:" << ::WSAGetLastError() << endl;  
  102.             return -1;  
  103.         }  
  104.   
  105.         //解析  
  106.         int nTick = ::GetTickCount();  
  107.         if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))  
  108.         {  
  109.             cout << "Too few bytes from " << ::inet_ntoa(from.sin_addr) << endl;  
  110.         }  
  111.   
  112.         ICMP_HDR *pRecvIcmp = (ICMP_HDR*)(recvBuf + sizeof(IPHeader));  
  113.         if(pRecvIcmp->icmp_type != 0)  
  114.         {  
  115.             cout << "nonecho type " << pRecvIcmp->icmp_type << " recvd" << endl;  
  116.             return -1;  
  117.         }  
  118.         if(pRecvIcmp->icmp_id != ::GetCurrentProcessId())  
  119.         {  
  120.             cout << "someone ele's packet!" << endl;  
  121.             return -1;  
  122.         }  
  123.   
  124.         cout << nRet << " bytes from " << inet_ntoa(from.sin_addr) ;  
  125.         cout << "icmp_seq = " << pRecvIcmp->icmp_sequence ;  
  126.         cout << "time: " << nTick - pRecvIcmp->icmp_timnestamp << " ms";  
  127.         cout << endl;  
  128.         Sleep(1000);  
  129.     }  
  130.   
  131.   
  132.     return 0;  
  133. }  



                                                                                                         jofranks  13.7.24 于南昌

版权声明:本文为博主原创文章,未经博主允许不得转载。

你可能感兴趣的:(网络编程深入研究,网络编程)