ping,VC实现

与窗口类结合使用

 

 

#pragma once

#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8 // minimum 8 byte icmp packet (just header)
#define STATUS_FAILED 0xFFFF
#define DEF_PACKET_SIZE    32
#define DEF_PACKET_NUMBER  4    /* ·¢ËÍÊý¾Ý±¨µÄ¸öÊý */
#define MAX_PACKET 1024
#define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
#define xfree(p) HeapFree (GetProcessHeap(),0,(p))

    /* The IP header */
typedef struct iphdr {
    unsigned int h_len:4; // length of the header
    unsigned int version:4; // Version of IP
    unsigned char tos; // Type of service
    unsigned short total_len; // total length of the packet
    unsigned short ident; // unique identifier
    unsigned short frag_and_flags; // flags
    unsigned char ttl;
    unsigned char proto; // protocol (TCP, UDP etc)
    unsigned short checksum; // IP checksum
    unsigned int sourceIP;
    unsigned int destIP;
}IpHeader;

//ICMP header
typedef struct icmphdr {
    BYTE i_type; //ICMPÀàÐÍÂ룬»ØËÍÇëÇóµÄÀàÐÍÂëΪ8
    BYTE i_code; /* type sub code */
    USHORT i_cksum; //УÑéºÍ
    USHORT i_id; //ICMPÊý¾Ý±¨IDºÅ
    USHORT i_seq; //ICMPÊý¾Ý±¨ÐòÁкÅ
    /* This is not the std header, but we reserve space for time */
    ULONG timestamp; //ʱ¼ä´Á£¬¿ÉÑ¡
}IcmpHeader;

class CPing
{
public:
    CPing(void);
    ~CPing(void);
private:
    void fill_icmp_data(char *, int);
    USHORT checksum(USHORT *, int);
    int decode_resp(char *,int ,struct sockaddr_in *);
    void printResult( HWND hWnd );
public:
    void DoPing(int times,LPTSTR url,HWND hWnd);
private:
    WSADATA wsaData;
    SOCKET sockRaw;
    struct sockaddr_in dest,from;
    struct hostent * hp;
    int bread,datasize;
    int fromlen;
    int timeout;
    int statistic;
    char *dest_ip;
    char *icmp_data;
    char *recvbuf;
    unsigned int addr;
    USHORT seq_no;
    char szResult[256];
};

 

 

 



#pragma pack(4)
#include "stdafx.h"
#include   "winsock2.h"
#pragma comment(lib,"Ws2_32.lib")
#include   "stdlib.h"
#include   "stdio.h"
#include    "Ping.h"


CPing::CPing(void)
{
    timeout = 1000;
    statistic = 0;  /* ÓÃÓÚͳ¼Æ½á¹û */
    addr=0;
    seq_no = 0;
    //szResult = "E";//ÓÃÈÎÒâ×Ö·û³õʼ»¯
    datasize = DEF_PACKET_SIZE;
    fromlen = sizeof(from);
}

CPing::~CPing(void)
{
}

//private method
int CPing::decode_resp(char *buf, int bytes,struct sockaddr_in *from) {
    IpHeader *iphdr;
    IcmpHeader *icmphdr;
    unsigned short iphdrlen;
    iphdr = (IpHeader *)buf;
    iphdrlen = (iphdr->h_len) * 4 ; // number of 32-bit words *4 = bytes
    if (bytes < iphdrlen + ICMP_MIN) {
        wsprintf(szResult,TEXT("Too few bytes from %s /r/r/n"),inet_ntoa(from->sin_addr));
    }
    icmphdr = (IcmpHeader*)(buf + iphdrlen);
    if (icmphdr->i_type != ICMP_ECHOREPLY) {
        wsprintf(szResult,TEXT("non-echo type %d recvd /r/r/n"),icmphdr->i_type);
        return 1;
    }
    if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) {
        wsprintf(szResult,TEXT("someone else''s packet! /r/r/n") );
        return 1;
    }
//    printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));
//    printf(" icmp_seq = %d. ",icmphdr->i_seq);
//    printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp);
//    printf("/n");
    wsprintf(szResult,TEXT("%d bytes from %s: icmp_seq = %d. time: %d ms /r/r/n"),bytes,inet_ntoa(from->sin_addr),icmphdr->i_seq,GetTickCount()-icmphdr->timestamp);
    return 0;
}

USHORT CPing::checksum(USHORT *buffer, int size)
{
    unsigned long cksum=0;
    while(size >1) {
        cksum+=*buffer++;
        size -=sizeof(USHORT);
    }
    if(size) {
        cksum += *(UCHAR*)buffer;
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);
    return (USHORT)(~cksum);
}
/*
Helper function to fill in various stuff in our ICMP request.
*/
void CPing::fill_icmp_data(char * icmp_data, int datasize)
{
    IcmpHeader *icmp_hdr;
    char *datapart;
    icmp_hdr = (IcmpHeader*)icmp_data;
    icmp_hdr->i_type = ICMP_ECHO;
    icmp_hdr->i_code = 0;
    icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
    icmp_hdr->i_cksum = 0;
    icmp_hdr->i_seq = 0;
    datapart = icmp_data + sizeof(IcmpHeader);
    //
    // Place some junk in the buffer.
    //
    memset(datapart,'E', datasize - sizeof(IcmpHeader));
}

void CPing::printResult( HWND hWnd )
{
        int   nLen = ::GetWindowTextLength( hWnd );
        ::SendMessage(hWnd,EM_SETSEL,nLen,-1);
        ::SendMessage(hWnd,EM_REPLACESEL,0,(LPARAM)szResult);
}

//public method
void CPing::DoPing( int times,LPTSTR url,HWND hWnd )
{
    if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0)
    {                    //ΪÁËÔÚÓ¦ÓóÌÐòµ±Öе÷ÓÃÈκÎÒ»¸öWinsock APIº¯Êý£¬Ê×ÏȵÚÒ»¼þÊÂÇé¾ÍÊDZØÐëͨ¹ýWSAStartupº¯ÊýÍê³É¶ÔWinsock·þÎñµÄ³õʼ»¯
        wsprintf(szResult,"WSAStartup failed: %d /r/r/n",GetLastError());
        printResult( hWnd );
        return;
    }
    sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);//´´½¨Ò»¸öÓëÖ¸¶¨´«ËÍ·þÎñÌṩÕßÀ¦°óµÄÌ×½Ó¿Ú£¬¿ÉÑ¡µØ´´½¨ºÍ/»ò¼ÓÈëÒ»¸öÌ×½Ó¿Ú×é;·µ»ØÐÂÌ×½Ó¿ÚÃèÊö×Ö£¬»òINVALID_SOCKET
    //
    //×¢£ºÎªÁËʹÓ÷¢ËͽÓÊÕ³¬Ê±ÉèÖÃ(¼´ÉèÖÃSO_RCVTIMEO, SO_SNDTIMEO)£¬
    //    ±ØÐ뽫±ê־λÉèΪWSA_FLAG_OVERLAPPED !
    //
    if (sockRaw == INVALID_SOCKET)
    {
        wsprintf(szResult,"WSASocket() failed: %d /r/r/n",WSAGetLastError());
        printResult( hWnd );
        return;
    }
    bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)); //ÉèÖýÓÊÕ³¬Ê±,sets a socket option,return zero or a value of SOCKET_ERROR
    if(bread == SOCKET_ERROR)
    {
        wsprintf(szResult,"failed to set recv timeout: %d /r/r/n",WSAGetLastError());
        printResult( hWnd );
        return;
    }
    timeout = 1000;
    bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout)); //·¢Ëͳ¬Ê±
    if(bread == SOCKET_ERROR)
    {
        wsprintf(szResult,"failed to set send timeout: %d /r/r/n",WSAGetLastError());
        printResult( hWnd );
        return;
    }
    memset(&dest,0,sizeof(dest));
    hp = gethostbyname( (const char*)url );
    if (!hp)
    {
        addr = inet_addr( (const char*)url ); //µØÖ·¸ñʽת»»
    }
    if ((!hp) && (addr == INADDR_NONE) )
    {
        wsprintf(szResult,"Unable to resolve %s /r/r/n",url);
        printResult( hWnd );
        return;
    }
    if (hp != NULL)
        memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
    else
        dest.sin_addr.s_addr = addr;
    if (hp)
        dest.sin_family = hp->h_addrtype;
    else
        dest.sin_family = AF_INET;
    dest_ip = inet_ntoa(dest.sin_addr); //This function converts an (Ipv4) Internet network address into a string in Internet standard dotted format
    datasize += sizeof(IcmpHeader);
    icmp_data = (char*)xmalloc(MAX_PACKET);
    recvbuf = (char*)xmalloc(MAX_PACKET);
    if (!icmp_data) {
        wsprintf(szResult,"HeapAlloc failed %d /r/r/n",GetLastError());
        printResult( hWnd );

        xfree( recvbuf );
        xfree( icmp_data );
        return;
    }

    memset(icmp_data,0,MAX_PACKET);
    fill_icmp_data(icmp_data,datasize);
    //
    //ÏÔʾÌáʾÐÅÏ¢
    //
    wsprintf(szResult,"CPinging %s [%s]..../r/r/n",(LPCSTR)dest_ip,url);
    printResult( hWnd );

    for(int i = 0;i < times;i++ )
    {
        int bwrote;
        ((IcmpHeader*)icmp_data)->i_cksum = 0;
        ((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
        ((IcmpHeader*)icmp_data)->i_seq = seq_no++;
        ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,datasize);
        bwrote = sendto( sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest) );
        if (bwrote == SOCKET_ERROR)
        {
            if (WSAGetLastError() == WSAETIMEDOUT)
            {
                wsprintf(szResult,"Request timed out./r/r/n");
                printResult( hWnd );
                continue;
            }
            wsprintf(szResult,"sendto failed: %d /r/r/n",WSAGetLastError());
            printResult( hWnd );

            xfree( recvbuf );
            xfree( icmp_data );
            return;
        }
        if (bwrote < datasize )
        {
            wsprintf(szResult,"Wrote %d bytes /r/r/n",bwrote);
            printResult( hWnd );
        }
        bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);
        if (bread == SOCKET_ERROR)
        {
            if (WSAGetLastError() == WSAETIMEDOUT)
            {
                wsprintf(szResult,"Request timed out./r/r/n");
                printResult( hWnd );
                continue;
            }
            wsprintf(szResult,"recvfrom failed: %d /r/r/n",WSAGetLastError());
            printResult( hWnd );

            xfree( recvbuf );
            xfree( icmp_data );
            return;
        }
        if(!decode_resp(recvbuf,bread,&from))
        {
            printResult( hWnd );
            statistic++; /* ³É¹¦½ÓÊÕµÄÊýÄ¿++ */
        }
        Sleep(1000);
    }//for(int i = 0;i<times;i++)
    wsprintf( szResult,"CPing statistics for %s /r/r/n    Packets: Sent = %d,Received = %d, Lost = %d (%2.0f%% loss)/r/r/n",
                        (LPCSTR)dest_ip,times,statistic,(times-statistic),(float)((times-statistic)/times)*100 );
    printResult( hWnd );
    WSACleanup();
    xfree( recvbuf );
    xfree( icmp_data );

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值