#include <winsock2.h> #include <iostream> #include <windows.h> using namespace std; #define DATA_SIZE 32 //icmp包数据大小 #define RECV_MAX_SZIE 1024 //接收的数据最大长度 #define IP_TTL 4 //optname #define MAX_HOP 30 //最大跃点数 #pragma comment(lib, "ws2_32.lib") typedef struct tag_icmphdr //icmp头 { unsigned char icmp_type; unsigned char icmp_code; unsigned short icmp_checksum; unsigned short icmp_id; unsigned short icmp_sequence; unsigned long icmp_timestamp; } ICMPHDR, *PICMPHDR; typedef struct tag_iphdr { unsigned char ip_verlen; unsigned char ip_tos; unsigned short ip_totallength; unsigned short ip_id; unsigned short ip_offset; unsigned char ip_ttl; unsigned char ip_protocol; unsigned short ip_checksum; unsigned int ip_srcaddr; unsigned int ip_destaddr; } IPHDR, *PIPHDR; void FillIcmp(char *icmp) { PICMPHDR p = (PICMPHDR)icmp; p->icmp_type = 8; p->icmp_code = 0; p->icmp_checksum = 0; p->icmp_id = (unsigned short)::GetCurrentProcessId(); p->icmp_sequence = 0; p->icmp_timestamp = 0; } USHORT CheckSum(USHORT *buf,int size) { USHORT cksum=0; while(size>1) { cksum+=*buf++; size-=sizeof(USHORT); } if(size) cksum+=*buf++; cksum=(cksum>>16)+(cksum&0xffff); cksum+=(cksum>>16); return (USHORT)(~cksum); } int g_size = sizeof(ICMPHDR)+DATA_SIZE; int _tmain(int argc, _TCHAR* argv[]) { WORD version = MAKEWORD(2,2); WSADATA data; WSAStartup(version, &data); if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2) { cout << "WSAStartup failed" << endl; WSACleanup(); return 0; } char ip[20]; cout << "tracert:"; cin >> ip; cout << endl << "Tracing route to" << ip << "[" << ip << "]" << "with a maximum of 30 hops." << endl << endl; SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = inet_addr(ip); addr.sin_port = htons(0); SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); //创建原始套接字 int bOpt = 1; int outTime = 2000; int rst; rst = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&outTime, sizeof(int)); //设置发送超时 if (SOCKET_ERROR == rst) { cout << "setsockopt erro" << endl; closesocket(sock); WSACleanup(); return -1; } rst = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&outTime, sizeof(int)); //设置接收超时 if (SOCKET_ERROR == rst) { cout << "setsockopt erro" << endl; closesocket(sock); WSACleanup(); return -1; } char *icmp = (char*)malloc(g_size); //为icmp包申请内存 memset(icmp, 0, g_size); //内存空间置零 FillIcmp(icmp); //填充icmp包 unsigned short sequence = 0; //序列号 int count = 4; //发送请求次数 char recvbuf[RECV_MAX_SZIE]; //接收buf SOCKADDR_IN addrfrom; //接收地址 int len = sizeof(SOCKADDR); //地址大小 int ttl = 1; //TTL int result; while (1) { result = setsockopt(sock, IPPROTO_IP, IP_TTL, (char*)&ttl, sizeof(int)); if (SOCKET_ERROR == result) { cout << "setsockopt IP_TTL error" << endl; closesocket(sock); WSACleanup(); return -1; } ((PICMPHDR)icmp)->icmp_checksum = 0; ((PICMPHDR)icmp)->icmp_checksum = CheckSum((USHORT*)icmp, g_size); int nTickPre = ::GetTickCount(); result = sendto(sock, icmp, g_size, 0, (SOCKADDR*)&addr, sizeof(SOCKADDR)); //向目标主机发送icmp请求包 if (SOCKET_ERROR == result) { if (WSAETIMEDOUT == WSAGetLastError()) { cout << "time out" << endl; continue; } else { cout << "sendto error" << endl; closesocket(sock); WSACleanup(); return -1; } } result = recvfrom(sock, recvbuf, RECV_MAX_SZIE, 0, (SOCKADDR*)&addrfrom, &len); //接收路由器返回的“icmp超时”报文(ttl等于0) if (SOCKET_ERROR == result) { if (WSAETIMEDOUT == GetLastError()) { cout << ttl << ": " << "* "<< "time out" << endl; ++ttl; continue; } else { cout << "recvform error" << endl; closesocket(sock); WSACleanup(); return -1; } } int nTickNow = ::GetTickCount(); int time = nTickNow - nTickPre; PIPHDR pip = (PIPHDR)recvbuf; char sip[20]; in_addr srcaddr; srcaddr.S_un.S_addr = pip->ip_srcaddr; strcpy(sip, inet_ntoa(srcaddr)); if (time == 0) cout << ttl << ": " << "<1ms "<< sip << endl; else cout << ttl << ": " << time << "ms "<< sip << endl; if (strcmp(ip, sip) == 0) { cout << "tracert complete" << endl; break; } ++ttl; if (ttl > 30) { break; } } return 0; }
socket实现tracert命令(控制台)
猜你喜欢
转载自blog.csdn.net/cbuttonst/article/details/7624575
今日推荐
周排行