socket 发送PING包

来源:互联网 发布:罗技键盘推荐 知乎 编辑:程序博客网 时间:2024/05/16 15:31

参考链接:
http://blog.csdn.net/zpxili/article/details/11542041
http://blog.csdn.net/cbuttonst/article/details/7610801
上面两位兄弟的是发一个icmp包,就收一次。在我的电脑上运行的时候,
估计是我的网络中有回环,结果每次收到的都是刚刚发出去的icmp包,
用wireshark抓包又能够抓到正确的reply包。调试了好久,修改如下。

//CPing.h

#ifndef CPING_HJ#define CPING_HJ#include <WinSock2.h>#include <string>typedef struct _SICMPHDR        //icmp{    unsigned char    icmp_type;    unsigned char    icmp_code;        unsigned short    icmp_checksum;    unsigned short    icmp_id;    unsigned short    icmp_sequence;    unsigned long    icmp_timestamp;} ICMPHDR, *PICMPHDR;typedef struct _SIPHDR        //ip{    UCHAR    ip_hVerLen;    UCHAR    ip_TOS;    USHORT    ip_Length;    USHORT    ip_ID;    USHORT    ip_Flags;    UCHAR    ip_TTL;    UCHAR    ip_Protacol;    USHORT    ip_Checksum;    ULONG    ip_Source;    ULONG    ip_Destination;} IPHDR;class CPing{public:    CPing();    ~CPing();    void m_vPing();private:    bool m_bSendData(char* pcBuf,int nBufLen,sockaddr_in* pstAddr);    bool m_bRecvData(char* pcBuf,int iBufLen,sockaddr_in* pstRecvAddr,int &riRecvLen);    void m_vInitICMP(PICMPHDR pstICMPHDR,int nSequence);    u_short m_usCheckSum(unsigned short *pusBuf,int iLen);    SOCKET m_iSocket;};#endif

//CPing.cpp

#include "CPing.h"#include <stdio.h>#define DATA_SIZE 32#define RECV_SIZE 1024const int SEND_PACKAGE_SIZE = 30;const int MAX_TIME = 3000; //msCPing::CPing(){    WSADATA wsaData;    WORD wVersion;    wVersion = MAKEWORD(2,2);    int nRet = WSAStartup(wVersion,&wsaData);    if( nRet != 0 )    {        printf("WSAStartup failed with error: %d\n", nRet);        return;    }    if( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )    {        printf("Could not find a usable version of Winsock.dll\n");        WSACleanup();        return;    }    m_iSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);    if( m_iSocket == INVALID_SOCKET )    {        printf("Socket err\n");        WSACleanup();        return;    }}CPing::~CPing(){    if( INVALID_SOCKET != m_iSocket )    {        closesocket(m_iSocket);    }    WSACleanup();}void CPing::m_vPing(){    char acName[] = "www.vidagrid.com";    hostent *pstHost = gethostbyname(acName);    if( pstHost == NULL )    {        printf("CPing::m_vPing() gethostbyname err\n");        return;    }    sockaddr_in stDesAddr;    stDesAddr.sin_family = AF_INET;    stDesAddr.sin_port = htons(0);    stDesAddr.sin_addr = *((struct in_addr *)(pstHost->h_addr));    //stDesAddr.sin_addr.s_addr = inet_addr("172.17.92.110");    char acIPAddr[23] = {0};    strcpy(acIPAddr, inet_ntoa(stDesAddr.sin_addr));    printf("CPing::m_vPing() acIPAddr: %s\n", acIPAddr);    int iSendBufLen = sizeof(ICMPHDR) + DATA_SIZE;    char* pcIcmp = new char[iSendBufLen];    memset(pcIcmp, 0, iSendBufLen);    PICMPHDR pstIcmp = (PICMPHDR)pcIcmp;    int iSequence = 0;    int iCount = SEND_PACKAGE_SIZE;    while ( iCount-- > 0 )    {        m_vInitICMP(pstIcmp, iSequence++);        pstIcmp->icmp_checksum = m_usCheckSum((unsigned short*)pstIcmp,sizeof(ICMPHDR) + DATA_SIZE); //校验值        m_bSendData((char*)pstIcmp, iSendBufLen, &stDesAddr);    }    int iMinimum = 0;    int iMaximum = 0;    int iSumTime = 0;    iCount = 0;    DWORD dwStartTime = GetTickCount();    printf("\nPinging %s [%s] with 32 bytes of data:\n\n", acName, acIPAddr);    while( (GetTickCount()-dwStartTime) <= MAX_TIME)    {        sockaddr_in stRcvAddr;        char acBuf[RECV_SIZE] = {0};        int iRecvLen = 0;        m_bRecvData(acBuf, sizeof(acBuf), &stRcvAddr, iRecvLen);        int iHeadLen = sizeof(IPHDR) + sizeof(ICMPHDR) + DATA_SIZE;        if( iRecvLen < iHeadLen )        {            printf("CPing::m_vPing() tool few data~\n\n");            continue;        }        IPHDR *ipHead = (IPHDR *)acBuf;        PICMPHDR icmpRecv = (PICMPHDR) (acBuf + sizeof(IPHDR) );        if( icmpRecv->icmp_type != 0 )        {            printf("CPing::m_vPing() Icmp Type err~, 0x%x\n\n", icmpRecv->icmp_type);            continue;        }        if( icmpRecv->icmp_id != GetCurrentProcessId() )        {            printf("CPing::m_vPing() Icmp ID err~\n\n");            continue;        }        int iCurUsedTime = GetTickCount() - icmpRecv->icmp_timestamp;        printf("Reply from %s: bytes=%d time=%ums TTL=%d\n",            inet_ntoa(stRcvAddr.sin_addr),             DATA_SIZE,             iCurUsedTime,            ipHead->ip_TTL);        iSumTime += iCurUsedTime;        if(iCount != 0)        {            if(iCurUsedTime<iMinimum) iMinimum = iCurUsedTime;            else if(iCurUsedTime>iMaximum) iMaximum = iCurUsedTime;        }        else        {            iMinimum = iCurUsedTime;            iMaximum = iCurUsedTime;        }        iCount++;    }    //show statistics    printf("\nPing statistics for %s:\n", acIPAddr);    printf("\tPackets: Sent = %d, Received = %d, Lost = %d (%.2lf%% loss),\n",         SEND_PACKAGE_SIZE, iCount, SEND_PACKAGE_SIZE-iCount, ((double)(SEND_PACKAGE_SIZE-iCount))/SEND_PACKAGE_SIZE*100 );    printf("Approximate round trip times in milli-seconds:\n");    printf("\tMinimum = %dms, Maximum = %dms, Average = %dms\n",         iMinimum, iMaximum, iSumTime/iCount);    delete pcIcmp;    getchar();}bool CPing::m_bSendData(char* pcBuf,int iBufLen,sockaddr_in* pstAddr){    printf("CPing::m_bSendData() \n");    if( pstAddr == NULL )    {        printf("CPing::m_bSendData() pstAddr == NULL\n");        return false;    }    int iTimeout = 1000;    int iRet = setsockopt(m_iSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&iTimeout, sizeof(int));    if( iRet == SOCKET_ERROR )    {        printf("CPing::m_bSendData() setsockopt SO_SNDTIMEO err\n");        return false;    }    iRet = sendto(m_iSocket, pcBuf, iBufLen, 0, (sockaddr*)pstAddr, sizeof(sockaddr));    if( iRet == SOCKET_ERROR )    {        if (WSAETIMEDOUT == WSAGetLastError())        {            printf("CPing::m_bSendData() timeout err\n");            return false;        }        else        {            printf("CPing::m_bSendData() sendto err\n");            return false;        }    }    return true;}bool CPing::m_bRecvData(char* pcBuf,int iBufLen,sockaddr_in* pstRecvAddr,int &riRecvLen){    printf("CPing::m_bRecvData() \n");    if( INVALID_SOCKET == m_iSocket )    {        printf("CPing::m_bRecvData() INVALID_SOCKET\n");        return false;    }    int iTimeout = 1000;    int iRet = setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO , (char*)&iTimeout, sizeof(int));    if( SOCKET_ERROR == iRet )    {        printf("CPing::m_bRecvData() setsockopt SO_RCVTIMEO error\n");        return false;    }    int nAddrLen = sizeof(sockaddr);    iRet = recvfrom(m_iSocket, pcBuf, iBufLen, 0, (sockaddr*)pstRecvAddr, &nAddrLen);    if( SOCKET_ERROR == iRet )    {        if (WSAETIMEDOUT == WSAGetLastError())        {            printf("CPing::m_bRecvData() timeout err\n");            return false;        }        else        {            printf("CPing::m_bRecvData() recvfrom err\n");            return false;        }    }    riRecvLen = iRet;    return true;}void CPing::m_vInitICMP(PICMPHDR pstICMPHDR,int iSequence){    if( pstICMPHDR == NULL )        return;    pstICMPHDR->icmp_type = 8; //request    pstICMPHDR->icmp_code = 0; //icmp request    pstICMPHDR->icmp_sequence = iSequence;    pstICMPHDR->icmp_id = (unsigned short)GetCurrentProcessId();    pstICMPHDR->icmp_timestamp = GetTickCount();    pstICMPHDR->icmp_checksum = 0; //校验值}unsigned short CPing::m_usCheckSum(unsigned short *pusBuf,int iLen){    USHORT cksum=0;    while(iLen>1)    {        cksum+=*pusBuf++;        iLen-=sizeof(USHORT);    }    if(iLen)    {        cksum+=*pusBuf++;    }    cksum=(cksum>>16)+(cksum&0xffff);    cksum+=(cksum>>16);    return (USHORT)(~cksum);}

//main.cpp

#include "CPing.h"#include <stdio.h>#include <winsock2.h>#include <iostream>#include <windows.h>using namespace std;#pragma comment(lib, "ws2_32.lib")int main(){    CPing oPing;    oPing.m_vPing();    return 0;}

当icmp_type==8时,这是一个请求包(ECHO包)。
当icmp_type==0时,这是一个响应消息报(ECHO REPLY包),就是对请求包的回应。

0 0