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
  • 相关阅读:
    T-SQL 数据库数据的高级查询
    数据库 T-sql 基础语句
    数据库的定义、关系型数据库的四种约束。。
    linux上使用crontab任务调度
    pip list 显示出以下错误: DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] se
    python报错:NameError: name 'converter' is not defined
    python3报错:TypeError: can't concat bytes to str
    Fiddler如何手机抓包
    数据分析----VBA的使用
    Excel进行数据分析
  • 原文地址:https://www.cnblogs.com/mdgsf/p/4833275.html
Copyright © 2011-2022 走看看