谢谢.

解决方案 »

  1.   

    头文件:
    #ifndef __NET_ICMP_H__
    #define __NET_ICMP_H__#include <winsock2.h>
    ///////////////////////////////////////////////////////////////////////////
    // icmp struct
    typedef struct IP
    {
    unsigned char ip_ver : 4; /* 4位版本 */
    unsigned char ip_hlen : 4; /* 4位长度 */
    unsigned char ip_tos;         /* 8位服务类型 */
    unsigned short ip_len;         
    unsigned short ip_id;          
    unsigned short ip_off;         
    unsigned char ip_ttl;           
    unsigned char ip_p;          
    unsigned short ip_sum;         
    unsigned long ip_src;
    unsigned long ip_dst;
    } IP;typedef struct ICMP
    {
    unsigned char icmp_type;
    unsigned char icmp_code;
    unsigned short icmp_cksum;
    unsigned short icmp_id;
    unsigned short icmp_seq;
    unsigned long icmp_data;
    } ICMP;#define SEND_BUFFER_LEN 1024
    #define SEND_SIZE 32 
    #define ICMP_ECHO 8
    #define ICMP_ECHOREPLY 0///////////////////////////////////////////////////////////////////////////////
    // class CNetIcmp define
    class CNetIcmp
    {
    public:
    virtual int InitSocket(const char *lpDestHost="127.0.0.1", int nTimeout=1000);
    virtual int Ping(); CNetIcmp();
    virtual ~CNetIcmp();private:
    int SetIcmpData();private:
    void ParseRecvMessage(const char* lpData, int len);
    unsigned short CheckSum(unsigned short* lpData, int nLen);
    SOCKET m_sockfd;
    struct sockaddr_in m_addr_in;
    struct sockaddr_in m_from_addr_in; int m_pid; char m_szbuffer[SEND_BUFFER_LEN];
    };#endif实现文件:
    #include <NETICMP.H>
    #include <process.h>
    #include <stdio.h>CNetIcmp::CNetIcmp()
    {
    m_pid = getpid();
    }CNetIcmp::~CNetIcmp()
    {
    }int CNetIcmp::Ping()
    {
    int nLen = SetIcmpData();

    if ((sendto(m_sockfd, (char*)m_szbuffer, nLen, 0, (struct sockaddr*)&m_addr_in, sizeof(m_addr_in))) < 0)
    {
    printf("目标主机不可到达。\n");
    return WSAGetLastError();
    } char szRecvBuffer[SEND_BUFFER_LEN];
    ::memset(szRecvBuffer, 0, sizeof(szRecvBuffer)); memset((char*)&m_from_addr_in, 0, sizeof(m_from_addr_in));
    int nAddrLen = sizeof(m_from_addr_in);

    int nRecvLen = 0;
    if (0 > (nRecvLen = recvfrom(m_sockfd, (char*)szRecvBuffer, sizeof(szRecvBuffer), 0, (struct sockaddr*)&m_from_addr_in, &nAddrLen)))
    {
    ::printf("应答超时!\n");
    return WSAGetLastError();
    } ParseRecvMessage(szRecvBuffer, nRecvLen); return 0;
    }int CNetIcmp::InitSocket(const char *lpDestHost, int nTimeout)
    {
    WSADATA wsaData;
    WORD wVersionRequested;
    struct protoent* ppe; wVersionRequested = MAKEWORD(2, 0); if (::WSAStartup(wVersionRequested, &wsaData))
    {
    return 0 - WSAGetLastError();
    }

    if (!(ppe = getprotobyname("icmp")))
    {
    return 0 - WSAGetLastError();
    } if (SOCKET_ERROR == (m_sockfd = socket(AF_INET, SOCK_RAW, ppe->p_proto)))
    {
    return 0 - WSAGetLastError();
    } if (SOCKET_ERROR == setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&nTimeout, sizeof(nTimeout)))
    {
    return 0 - WSAGetLastError();
    } if (SOCKET_ERROR == setsockopt(m_sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeout, sizeof(nTimeout)))
    {
    return 0 - WSAGetLastError();
    } m_addr_in.sin_family = AF_INET;
    m_addr_in.sin_addr.s_addr = inet_addr(lpDestHost); return 0;
    }int CNetIcmp::SetIcmpData()
    {
    int npackagesize = SEND_SIZE + 8; ICMP* picmp = NULL;

    memset(m_szbuffer, 0, sizeof(m_szbuffer));
    picmp = (ICMP*)m_szbuffer; picmp->icmp_type = ICMP_ECHO;
    picmp->icmp_code = 0;
    picmp->icmp_seq = 0;
    picmp->icmp_id = m_pid;
    picmp->icmp_data = GetTickCount();
    picmp->icmp_cksum = CheckSum((unsigned short*)picmp, npackagesize); return npackagesize;
    }unsigned short CNetIcmp::CheckSum(unsigned short *lpData, int nLen)
    {
    int nLeft = nLen;
    unsigned long sum = 0;

    unsigned short *w = lpData;
    unsigned short answer = 0; while(nLeft > 1)
    {
    sum += *w++;
    nLeft -= 2;
    } if(nLeft == 1)
    {       
    *(unsigned char*)(&answer) = *(unsigned char*)w;
    sum += answer;
    } sum  = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    answer  = ~sum;

    return answer;
    }void CNetIcmp::ParseRecvMessage(const char *lpData, int len)
    {
    IP* ip;
    ICMP* icmp;
    double rtt;
    int iphdrlen; ip=(IP*)lpData; iphdrlen = ip->ip_hlen * 4;    

    icmp=(ICMP*)(lpData + iphdrlen);           

    //if( (icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == m_pid) )
    if( 1 )

    len = len - iphdrlen - 8;   
    rtt = GetTickCount() - icmp->icmp_data;   printf("Reply from %s: bytes=%d time=%.0fms TTL=%d icmp_seq=%u\n",             
    inet_ntoa(m_from_addr_in.sin_addr),
    len,
    rtt,
    ip->ip_ttl,
    icmp->icmp_seq);
    return;
    }
    return ;
    }