ICMP构建报文,实现Ping
ckfan
posted @ 2012年11月05日 19:47
in 技术blog
, 2015 阅读
首先要了解下ICMP,先前用IcmpSendEcho实现了Ping功能,见 http://ckfan.is-programmer.com/posts/36168.html ICMP:是Internet 控制信息协议(ICMP)是 IP 组的一个整合部分,通过 IP 包传送的 ICMP 信息主要用于涉及网络 操作或错误操作的不可达信息。 ICMP 的报文类型:
这里再说说下,我原先一些误区: 1.ICMP没有端口,它并不像TCP/UDP那样有发到特定的接收端口,它是控制协议,服务于IP层。当某个网关发现传输错误时,立即向信源主机发 送 ICMP报文,报告出错信息,让信源主机采取相应处理措施,它是一种差错和控制报文协议,不仅用于传输差错报文,还传输控制报文。 2.ICMP 包发送是不可靠的。
code: .h #pragma once #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") #pragma pack(1) // ICMP 头部 typedef struct _ihdr { BYTE i_type; // 8位类型 BYTE i_code; // 8位代码 USHORT i_cksum; // 16位校验和 USHORT i_id; // 识别号 USHORT i_seq; // 报文序列号 ULONG timestamp; // 时间戳 }ICMP_HEADER; typedef struct _iphdr{ unsigned char h_lenver; // 4 位IP版本号+4位首部长度 unsigned char tos; // 8位服务类型TOS unsigned short total_len; // 16位IP包总长度(字节) unsigned short ident; // 16位标识, 用于辅助IP包的拆装,本实验不用,置零 unsigned short frag_and_flags; // 3位标志位+13位偏移位, 也是用于IP包的拆装,本实验不用,置零 unsigned char ttl; // 8位IP包生存时间 TTL unsigned char proto; // 8位协议 (TCP, UDP 或其他), 本实验置ICMP,置为1 unsigned short checksum; // 16位IP首部校验和,最初置零,等 // 所有包头都填写正确后,计算并替换. unsigned int sourceIP; // 32位源IP地址 unsigned int destIP; // 32位目的IP地址 }IP_HEADER; #pragma pack() class CIPing { public: CIPing(); ~CIPing(); // PING X.X.X.X BOOL Ping(LPCTSTR ip, int timeout); private: SOCKET s; }; .cpp #include "stdafx.h" #include "IPing.h" // 校验和 unsigned short CheckSum(unsigned short *addr, int count) { /* Compute Internet Checksum for "count" bytes * beginning at location "addr". */ register long sum = 0; while( count > 1 ) { /* This is the inner loop */ sum += *addr++; count -= sizeof(USHORT); } /* Add left-over byte, if any */ if( count > 0 ) sum += * (unsigned char *) addr; /* Fold 32-bit sum to 16 bits */ while (sum>>16) sum = (sum & 0xffff) + (sum >> 16); return (USHORT)~sum; } CIPing::CIPing() { } CIPing::~CIPing() { } // PING X.X.X.X BOOL CIPing::Ping(LPCTSTR ip, int timeout) { struct sockaddr_in addrSrc; struct sockaddr_in addrDest; ICMP_HEADER head; UCHAR ucSendBuf[1024]; UCHAR ucRecBuf[1024]; int recFromLen; IP_HEADER *pIpHdr = NULL; unsigned short len; // create if((s = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET) { return FALSE; } // 发送时限 setsockopt( s, SOL_SOCKET, SO_SNDTIMEO, ( char * )&timeout, sizeof( int ) ); // 接收时限 setsockopt( s, SOL_SOCKET, SO_RCVTIMEO, ( char * )&timeout, sizeof( int ) ); memset(&addrSrc, 0, sizeof(sockaddr_in)); // addr addrSrc.sin_family = AF_INET; addrSrc.sin_addr.s_addr = inet_addr(ip); // 填充ICMP首部 memset(&head, 0, sizeof(ICMP_HEADER)); // 回显应答 head.i_type = 0; head.i_code = 0; // 校验和置0 head.i_cksum = 0; head.i_id = 2; // 时间戳 head.timestamp = GetTickCount(); head.i_seq = 999; memset(ucSendBuf, 0, 1024); memcpy(ucSendBuf, &head, sizeof(ICMP_HEADER)); memset(ucSendBuf + sizeof(ICMP_HEADER), '1', 32); head.i_cksum = CheckSum((USHORT*)ucSendBuf, sizeof(ICMP_HEADER) + 32); memcpy(ucSendBuf, &head, sizeof(ICMP_HEADER)); // 发送 if(sendto(s, (char*)ucSendBuf, sizeof(ICMP_HEADER) + 32, 0, (struct sockaddr*)&addrSrc,sizeof(addrSrc)) == SOCKET_ERROR) { closesocket(s); s = NULL; return FALSE; } memset(ucRecBuf, 0, 1024); memset(&addrDest, 0, sizeof(struct sockaddr)); recFromLen = sizeof(sockaddr); addrDest.sin_family = AF_INET; if (recvfrom(s, (char*)ucRecBuf, 1023, 0, (struct sockaddr*)&addrDest, &recFromLen) == SOCKET_ERROR) { if(WSAGetLastError() == WSAETIMEDOUT) { OutputDebugString("Time out...\n"); } closesocket(s); s = NULL; return FALSE; } closesocket(s); s = NULL; // 判断包的正确性 pIpHdr = (IP_HEADER *)ucRecBuf; // Number of 32-bit words * 4 = bytes // 计算ip包头长度 len = sizeof(unsigned long) * (pIpHdr->h_lenver & 0xf); memcpy(&head,& ucRecBuf[len], sizeof(ICMP_HEADER)); // 标识 if (head.i_id != 2) { return FALSE; } return TRUE; }
2024年1月16日 15:22
The the next occasion I read a blog, Hopefully it doesnt disappoint me around this blog. What i’m saying is, I know it was my substitute for read, but I really thought youd have something interesting to express. All I hear is often a number of whining about something you could fix in the event you werent too busy in search of attention