socket实现ping功能

来源:互联网 发布:用友u8数据库修复工具 编辑:程序博客网 时间:2024/06/10 08:55
#include <winsock2.h>#include <iostream>#include <windows.h>using namespace std;#define DATA_SIZE 32#define RECV_MAX_SZIE 1024#pragma comment(lib, "ws2_32.lib")typedef struct tag_icmphdr      //icmp头{    unsigned char   icmp_type;    unsigned char   icmp_code;      unsigned short  icmp_checksum;    unsigned short  icmp_id;    unsigned short  icmp_sequence;} ICMPHDR, *PICMPHDR;typedef struct tag_iphdr        //ip头{    UCHAR   iphVerLen;    UCHAR   ipTOS;    USHORT  ipLength;    USHORT  ipID;    USHORT  ipFlags;    UCHAR   ipTTL;    UCHAR   ipProtacol;    USHORT  ipChecksum;    ULONG   ipSource;    ULONG   ipDestination;} IPHDR;USHORT CheckSum(USHORT *buf,int size){    USHORT cksum=0;    while(size>1)    {        cksum+=*buf++;        size-=sizeof(USHORT);    }    if(size)        cksum+=*buf++;    cksum=(cksum>>16)+(cksum&0xffff);    cksum+=(cksum>>16);    return (USHORT)(~cksum);}void FillIcmp(PICMPHDR p){    p->icmp_type = 8;    p->icmp_code = 0;    p->icmp_checksum = 0;    p->icmp_id = (unsigned short)::GetCurrentProcessId();    p->icmp_sequence = 0;}int main(){    WORD version = MAKEWORD(2,2);    WSADATA data;    WSAStartup(version, &data);    if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2)    {        cout << "WSAStartup failed" << endl;        WSACleanup();        return -1;    }    char host[] = "www.baidu.com";    struct hostent *he = gethostbyname(host);    if (!he)    {        return -1;    }    struct in_addr **addr_list = (struct in_addr **) he->h_addr_list;    SOCKADDR_IN addr;                                                           //目标主机地址    addr.sin_family = AF_INET;    addr.sin_addr = *addr_list[0];    addr.sin_port = htons(0);    SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);                      //创建原始套接字    int outTime = 1000;    int rst;    rst = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&outTime, sizeof(int));  //设置发送超时    if (SOCKET_ERROR == rst)    {        cout << "setsockopt erro" << endl;        closesocket(sock);        WSACleanup();        return -1;    }    rst = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&outTime, sizeof(int));  //设置接收超时    if (SOCKET_ERROR == rst)    {        cout << "setsockopt erro" << endl;        closesocket(sock);        WSACleanup();        return -1;    }    char *icmp = (char*)malloc(sizeof(ICMPHDR)+DATA_SIZE);                      //为icmp包申请内存    memset(icmp, 0, sizeof(ICMPHDR)+DATA_SIZE);                                 //内存空间置零    PICMPHDR picmp = (PICMPHDR)icmp;    FillIcmp(picmp);                                                            //填充icmp包    unsigned short sequence = 0;                                                //序列号    int count = 4;                                                              //发送请求次数    char recvbuf[RECV_MAX_SZIE];                                                //接收buf    SOCKADDR_IN addrfrom;                                                       //接收地址    int len = sizeof(SOCKADDR);                                                 //地址大小    int ipTTL = 0;                                                              //TTL    while (count--)    {        picmp->icmp_checksum = 0;        picmp->icmp_sequence = sequence++;        picmp->icmp_checksum = CheckSum((USHORT*)icmp, sizeof(ICMPHDR)+DATA_SIZE);        DWORD send_ts = ::GetTickCount();        int result;        result = sendto(sock, icmp, sizeof(ICMPHDR)+DATA_SIZE, 0, (SOCKADDR*)&addr, sizeof(SOCKADDR));  //向目标主机发送icmp请求包        if (SOCKET_ERROR == result)        {            if (WSAETIMEDOUT == WSAGetLastError())            {                cout << "time out" << endl;                continue;            }            else            {                cout << "sendto error" << endl;                closesocket(sock);                WSACleanup();                return -1;            }        }        while ((result = recvfrom(sock, recvbuf, RECV_MAX_SZIE, 0, (SOCKADDR*)&addrfrom, &len)) > 0)        {            if (addr.sin_addr.s_addr == addrfrom.sin_addr.s_addr)            {                break;            }        }        if (SOCKET_ERROR == result)        {            if (WSAETIMEDOUT == GetLastError())            {                cout << "time out" << endl;                continue;            }            else            {                cout << "recvform error" << endl;                closesocket(sock);                WSACleanup();                return -1;            }        }        DWORD recv_ts = ::GetTickCount();        if (result < sizeof(IPHDR) + sizeof(ICMPHDR) + DATA_SIZE)        {            cout << "too few bytes" << endl;        }        IPHDR *pIP = (IPHDR*)recvbuf;        ipTTL = (int)pIP->ipTTL;    //获取目标主机TTL        PICMPHDR p = (PICMPHDR)(recvbuf+sizeof(IPHDR));        if (p->icmp_type != 0)        {            cout << "error type " << p->icmp_type << " receved" << endl;            return -1;        }        cout << "reply from: " << inet_ntoa(addrfrom.sin_addr) << " time: " << recv_ts - send_ts << "ms" << " TTL=" << ipTTL << endl;    }    getchar();    return 0;}
0 0