// Ping_Project.cpp : Defines the entry point for the console application. // #include <winsock2.h> #include "stdafx.h" #include <Windows.h> #include <stdio.h> #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; }