抄写了一次ping程序

本文介绍了一个使用C++实现的自定义Ping程序,该程序通过发送ICMP请求并接收响应来测试网络连通性。文章详细展示了如何构建IP和ICMP头部信息,计算校验和,并解析回应数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// Ping_Project.cpp : Defines the entry point for the console application.  
//  
#include   
#include "stdafx.h"  
#include   
#include   
#pragma comment(lib,"WS2_32.lib")  
char szDestIP[]="119.147.15.11";  
int checksum(USHORT* buff, int size);  
int recSize=0;  
BOOL    HandPacket(char * Packet, SOCKADDR_IN sockFrom);  
#define PROTO_ICMP    1  
#define PROTO_IGMP    2  
#define PROTO_TCP     6  
#define PROTO_UDP     17  
typedef struct _IPHeader        // 20字节的IP头  
{  
    UCHAR     iphVerLen;      // 版本号和头长度(各占4位)  
    UCHAR     ipTOS;          // 服务类型   
    USHORT    ipLength;       // 封包总长度,即整个IP报的长度  
    USHORT    ipID;           // 封包标识,惟一标识发送的每一个数据报  
    USHORT    ipFlags;        // 标志  
    UCHAR     ipTTL;          // 生存时间,就是TTL  
    UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等  
    USHORT    ipChecksum;     // 校验和  
    ULONG     ipSource;       // 源IP地址  
    ULONG     ipDestination;  // 目标IP地址  
} IPHeader, *PIPHeader;   
typedef struct ICMPHeader   
{  
    unsigned char   icmp_type;  
    unsigned char   icmp_code;  
    unsigned short  icmp_checksum;  
    //回显头  
    unsigned short  icmd_id;  
    unsigned short  icmp_sequence;  
    unsigned long   icmp_timestamp;  
} ICMPH;  
int main(int argc, char* argv[])  
{  
    printf("%d,%d/r/n",sizeof(IPHeader),sizeof(ICMPH));  
    WSADATA wsaData;   
    if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0)  
        ;  
    SOCKET  sRaw    =socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);  
    SOCKADDR_IN dest;  
    char sendBuf[sizeof(ICMPHeader)+32];  
    dest.sin_family =   AF_INET;  
    dest.sin_port   =   htons(0);  
    dest.sin_addr.S_un.S_addr   =   inet_addr(szDestIP);  
    ICMPHeader  *icmpHeader =(ICMPHeader*)sendBuf;  
    ZeroMemory(icmpHeader, sizeof(ICMPHeader));  
    icmpHeader->icmp_code    =   0;  
    icmpHeader->icmp_type    =   8;  
    icmpHeader->icmp_checksum    =   0;  
    icmpHeader->icmd_id      =   (unsigned short)GetCurrentProcessId();  
    int count=0;  
    char recBuff[1024];  
    SOCKADDR_IN from;  
    int nLen = sizeof(from);  
    int nRet=0;  
    while(1)  
    {  
        count++;  
        if (count==4)  
        {  
            break;  
        }  
        icmpHeader->icmp_code    =   0;  
        icmpHeader->icmp_type    =   8;  
        icmpHeader->icmd_id      =   (unsigned short)GetCurrentProcessId();  
        icmpHeader->icmp_sequence    =count;  
        icmpHeader->icmp_timestamp   =GetTickCount();  
        icmpHeader->icmp_checksum    =0;//有必要设置为0再算  
        icmpHeader->icmp_checksum    =checksum((USHORT*)sendBuf, sizeof(sendBuf));  
        sendto(sRaw, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&dest, sizeof(dest));  
        if(nRet == SOCKET_ERROR)  
        {  
            printf(" sendto() failed: %d /n", ::WSAGetLastError());  
        //  return -1;  
            continue;  
        }  
        ZeroMemory(recBuff, 1024);  
        recSize=nRet    =recvfrom(sRaw, recBuff, 1024, 0, (SOCKADDR*)&from, &nLen);  
        if (nRet    ==  SOCKET_ERROR)  
        {  
            if (WSAGetLastError()==WSAETIMEDOUT)  
            {  
                printf("request time out!/r/n");  
                return 1;  
            }  
            printf(" recvfrom() failed: %d /n", ::WSAGetLastError());  
        //  return -1;  
            continue;  
        }  
        if(nRet < sizeof(IPHeader) + sizeof(ICMPHeader))  
        {  
            printf(" Too few bytes from %s /n", ::inet_ntoa(from.sin_addr));  
        }  
        HandPacket((char*)recBuff, from);  
    //  Sleep(11);  
    }  
    WSACleanup();  
    return 0;  
}  
///////////////////////////////////////////////////  
int checksum(USHORT* buff, int size)  
{  
/* 
    unsigned long cksum = 0; 
    while(size>1) 
    { 
        cksum += *buff++; 
        size -= sizeof(USHORT); 
    } 
    // 是奇数 
    if(size) 
    { 
        cksum += *(UCHAR*)buff; 
    } 
    // 将32位的chsum高16位和低16位相加,然后取反 
    cksum = (cksum >> 16) + (cksum & 0xffff); 
    cksum += (cksum >> 16);            
    return (USHORT)(~cksum); 
*/ 
        int checksum=0;  
        while(size>1)  
        {  
            checksum+=*(buff++);  
            size-=2;  
        }  
        if (size)  
        {  
            checksum+=*(UCHAR*)buff;  
        }  
        checksum    = (checksum>>16)+(checksum&0xffff);  
        checksum+=checksum>>16;  
        return ~checksum;  
}  
BOOL    HandPacket(char * Packet, SOCKADDR_IN sockFrom)  
{  
    IPHeader* ipHder=(IPHeader*)Packet;  
    ICMPHeader *icmphder=(ICMPHeader*)(Packet+sizeof(IPHeader));  
    if (icmphder->icmd_id!=GetCurrentProcessId())  
    {  
        printf("someone else's packet");  
        return TRUE;  
    }  
    if (icmphder->icmp_type!=0)  
    {  
        printf("not echo type icmpPacket");  
        return TRUE;  
    }  
    int nTick=GetTickCount();  
    printf("Reply %d bytes from %s:", strlen((char*)icmphder+sizeof(ICMPHeader)), inet_ntoa(sockFrom.sin_addr));  
    printf(" icmp_seq=%d. TTL=%d", icmphder->icmp_sequence,ipHder->ipTTL);  
    printf(" time: %dms Protocol:%d", nTick - icmphder->icmp_timestamp, ipHder->ipProtocol);  
    printf(" /n");  
//  printf(" ip: %d /r/n", ipHder->ipSource);  
    return TRUE;  

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/vincent_1011/archive/2009/08/25/4480347.aspx#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值