ICMP学习

#include "stdafx.h"
#include <WinSock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")

struct ICMPHeader
{
    BYTE type;          // ICMP packet type
    BYTE code;          // Type sub code
    USHORT checksum;
    USHORT id;
    USHORT seq;
    ULONG timestamp;    // not part of ICMP, but we need it
    BYTE ic_data[1];
};
struct IPHeader {
    unsigned char h_len : 4; //4位首部长度
    unsigned char ver : 4; //4位IP版本号
    unsigned char tos; //8位服务类型TOS
    unsigned short total_len; //16位总长度(字节)
    unsigned short ident; //16位标识
    unsigned short frag_and_flags; //3位标志位
    unsigned char ttl; //8位生存时间 TTL
    unsigned char proto; //8位协议 (TCP, UDP 或其他)
    unsigned short checksum; //16位IP首部校验和
    unsigned int sourceIP; //32位源IP地址
    unsigned int destIP; //32位目的IP地址
    ICMPHeader icmp_header;

};

USHORT ip_checksum(USHORT* buffer, int size)
{
    unsigned long cksum = 0;

    // Sum all the words together, adding the final byte if size is odd
    while (size > 1) {
        cksum += *buffer++;
        size -= sizeof(USHORT);
    }
    if (size) {
        cksum += *(UCHAR*)buffer;
    }

    // Do a little shuffling
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);

    // Return the bitwise complement of the resulting mishmash
    return (USHORT)(~cksum);
}
int _tmain(int argc, _TCHAR* argv[])
{
    char *host = "www.baidu.com";
    WSADATA ws;
    if(WSAStartup(MAKEWORD(2,2), &ws) != 0)
        goto clean;
    //需要管理员权限
    SOCKET cli = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (cli == INVALID_SOCKET)
        goto clean;

    sockaddr_in sockadd;
    sockadd.sin_family = AF_INET;
    sockadd.sin_port = 0;
    sockadd.sin_addr.S_un.S_addr = inet_addr(host);
    if (sockadd.sin_addr.S_un.S_addr == INADDR_NONE)
    {
        hostent* hp = gethostbyname(host);
        if (hp != 0) {
            memcpy(&(sockadd.sin_addr), hp->h_addr, hp->h_length);
            sockadd.sin_family = hp->h_addrtype;
        }
        else
        {
            cerr << "Failed to resolve " << host << endl;
            goto clean;
        }
    }

    //初始化ICMP头
    ICMPHeader IcmpHeader;
    IcmpHeader.type = 8;
    IcmpHeader.checksum = 0;
    IcmpHeader.code = 0;
    IcmpHeader.id = (USHORT)GetCurrentProcessId();
    IcmpHeader.seq = 0;
    IcmpHeader.timestamp = GetTickCount();
    IcmpHeader.checksum = ip_checksum((USHORT *)&IcmpHeader, sizeof(IcmpHeader));

    sockaddr_in from;
    int nAddLen = sizeof(from);
    //发送ICMP
    int nSend = sendto(cli, (char *)&IcmpHeader, sizeof(IcmpHeader), 0,
        (sockaddr *)&sockadd, sizeof(sockaddr));

    
    IPHeader recvBuff;

    //接受ICMP回复
    int recv = recvfrom(cli, (char *)&recvBuff,sizeof(IPHeader), 0,
        (sockaddr *)&from, &nAddLen);

    if (recvBuff.icmp_header.id != (USHORT)GetCurrentProcessId())
    {
        cout<<"Err:CurrentID"<<endl;
        goto clean;
    }
    cout << recv << " bytes from " <<
        inet_ntoa(from.sin_addr) << ", time " <<
        GetTickCount()-recvBuff.icmp_header.timestamp<<
        "ms."<<endl;

clean:
    WSACleanup();
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值