#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;
}
ICMP学习
最新推荐文章于 2023-12-28 14:10:55 发布