zoukankan      html  css  js  c++  java
  • socket 发送Ping包

    参考链接:
    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 1024
    const int SEND_PACKAGE_SIZE = 30;
    const int MAX_TIME = 3000; //ms
    CPing::CPing()
    {
        WSADATA wsaData;
        WORD wVersion;
        wVersion = MAKEWORD(2,2);
        int nRet = WSAStartup(wVersion,&wsaData);
        if( nRet != 0 )
        {
            printf("WSAStartup failed with error: %d
    ", nRet);
            return;
        }
        if( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )
        {
            printf("Could not find a usable version of Winsock.dll
    ");
            WSACleanup();
            return;
        }
        m_iSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
        if( m_iSocket == INVALID_SOCKET )
        {
            printf("Socket err
    ");
            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
    ");
            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
    ", 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("
    Pinging %s [%s] with 32 bytes of data:
    
    ", 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~
    
    ");
                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
    
    ", icmpRecv->icmp_type);
                continue;
            }
            if( icmpRecv->icmp_id != GetCurrentProcessId() )
            {
                printf("CPing::m_vPing() Icmp ID err~
    
    ");
                continue;
            }
            int iCurUsedTime = GetTickCount() - icmpRecv->icmp_timestamp;
            printf("Reply from %s: bytes=%d time=%ums TTL=%d
    ",
                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("
    Ping statistics for %s:
    ", acIPAddr);
        printf("	Packets: Sent = %d, Received = %d, Lost = %d (%.2lf%% loss),
    ", 
            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:
    ");
        printf("	Minimum = %dms, Maximum = %dms, Average = %dms
    ", 
            iMinimum, iMaximum, iSumTime/iCount);
        delete pcIcmp;
        getchar();
    }
    bool 
    CPing::m_bSendData(char* pcBuf,int iBufLen,sockaddr_in* pstAddr)
    {
        printf("CPing::m_bSendData() 
    ");
        if( pstAddr == NULL )
        {
            printf("CPing::m_bSendData() pstAddr == NULL
    ");
            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
    ");
            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
    ");
                return false;
            }
            else
            {
                printf("CPing::m_bSendData() sendto err
    ");
                return false;
            }
        }
        return true;
    }
    bool 
    CPing::m_bRecvData(char* pcBuf,int iBufLen,sockaddr_in* pstRecvAddr,int &riRecvLen)
    {
        printf("CPing::m_bRecvData() 
    ");
        if( INVALID_SOCKET == m_iSocket )
        {
            printf("CPing::m_bRecvData() INVALID_SOCKET
    ");
            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
    ");
            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
    ");
                return false;
            }
            else
            {
                printf("CPing::m_bRecvData() recvfrom err
    ");
                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_type8时,这是一个请求包(ECHO包)。
    当icmp_type
    0时,这是一个响应消息报(ECHO REPLY包),就是对请求包的回应。

    My Github Blog: mdgsf.github.io
  • 相关阅读:
    UVa 116 单向TSP(多段图最短路)
    POJ 1328 Radar Installation(贪心)
    POJ 1260 Pearls
    POJ 1836 Alignment
    POJ 3267 The Cow Lexicon
    UVa 1620 懒惰的苏珊(逆序数)
    POJ 1018 Communication System(DP)
    UVa 1347 旅行
    UVa 437 巴比伦塔
    UVa 1025 城市里的间谍
  • 原文地址:https://www.cnblogs.com/mdgsf/p/4833275.html
Copyright © 2011-2022 走看看