首页 > 编程知识 正文

icmp报文的类型字段为8,tracert结果怎么看

时间:2023-05-06 14:45:31 阅读:15224 作者:907

# include iostream # include Winsock2. h # include ws2 tcpip.h # include ws2 IP def.husingnamespacestd; #pragmacomment(lib,' Ws2_32.lib ' )/IP标头typedefstructip _ header (unsignedcharhdr _ len 3:4; //4位头长度1位4字节,最多15*4字节(可选)无符号字符版本: 4; //4位版本号unsigned char tos; //8位服务类型unsigned short total_len; //16位全长统一短标识符; //16位标识符unsigned short frag_and_flags; //3位标志加13位切片偏移非唯一字符TTL; //8位生存时间不确定通道协议; //8位高位协议号unsigned short checksum; //16位校验和统一长源IP; //32位源IP地址不唯一长桌面; //32位目标IP地址(} IP_HEADER; //ICMP标头typedefstructicmp _ header { byte type; //8位字段字节码; //8位代码字段USHORT cksum; //16位校验和USHORT id; //16位标识符USHORT seq; //16位序列号(} ICMP_HEADER; //消息解码结构typedefstructdecode _ result { ushortusseqno; //序列号DWORD dwRoundTripTime; //往返时间in_addr dwIPaddr; //回复消息的IP地址(}DECODE_RESULT; //计算互联网校验和的函数ushortchecksum(ushort*pbuf,int iSize ) { unsigned long cksum=0; while(isize1) { cksum =*pBuf; isize-=sizeof(ushort ); (if ) iSize )如果iSize为正,则奇数字节cksum=*(uchar* ) pBuf; //添加字节以使其成为偶数字节(cksum=) cksum16 ) (cksum0xffff ); cksum=(cksum16 ); 返回(ushort ) (~cksum ); //解码数据包的booldecodeicmpresponse (char * pbuf,int iPacketSize,DECODE_RESULT DecodeResult,byte icmp _ echo _ replponse 如果//ip报头的长度以4字节为单位//数据包大小小于IP报头的ICMP报头,则数据报大小无效if(ipacketsize(int ) ) iiphdrlensizeof (icmp _ header ) ICMP消息类型至ID字段和序列号字段icmp _ header * picmphdr=(icmp _ header * ) pBuf iIpHdrLen ); //ICMP报头=接收到的缓冲数据IP报头USHORT usID,usSquNo; if (picmphdr-type==icmp _ echo _ reply )//ICMP回声响应消息({ usID=pIcmpHdr-id; //消息ID usSquNo=pIcmpHdr-seq; //消息序列号(else if (picmphdr-type==icmp _ time out )/icmp超时错误消息(/*以下操作与收到的icmp超时消息相关) (/char*pinneriphdr=pbufiphdrlenizeof(ICMP_HEADER); int iInnerIPHdrLen = ((IP_HEADER*)pInnerIpHdr)->hdr_len * 4; ICMP_HEADER* pInnerIcmpHdr = (ICMP_HEADER*)(pInnerIpHdr + iInnerIPHdrLen); usID = pInnerIcmpHdr->id; //报文ID usSquNo = pInnerIcmpHdr->seq; //序列号 } else { return false; } //检查ID和序列号以确定收到期待数据报 if (usID != (USHORT)GetCurrentProcessId() || usSquNo != DecodeResult.usSeqNo) { return false; } //记录IP地址并计算往返时间 DecodeResult.dwIPaddr.s_addr = pIpHdr->sourceIP; DecodeResult.dwRoundTripTime = GetTickCount() - DecodeResult.dwRoundTripTime; //处理正确收到的ICMP数据报 if (pIcmpHdr->type == ICMP_ECHO_REPLY || pIcmpHdr->type == ICMP_TIMEOUT) { //输出往返时间信息 if (DecodeResult.dwRoundTripTime) cout << " " << DecodeResult.dwRoundTripTime << "ms" << flush; else cout << " " << "<1ms" << flush; } return true;}int main(){ WSADATA wsa; if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { return -1; } char IpAddress[255]; cout << "请输入一个IP地址或域名:"; cin >> IpAddress; //得到IP地址,字符数字转整形 u_long ulDestIP = inet_addr(IpAddress); //转换不成功时按域名解析 if (ulDestIP == INADDR_NONE) { /*通过IP地址获取域名*/ hostent* pHostent = gethostbyname(IpAddress); if(pHostent) { ulDestIP = (*(in_addr*)pHostent->h_addr).s_addr; } else { cout << "输入的IP地址或域名无效!" << endl; WSACleanup(); return 0; } } cout << "Tracing roote to " << IpAddress << " with a maximum of 30 hops.n" << endl; /*填充目的端socket地址*/ sockaddr_in destSockAddr; ZeroMemory(&destSockAddr, sizeof(sockaddr_in)); destSockAddr.sin_family = AF_INET; destSockAddr.sin_addr.s_addr = ulDestIP; //创建原始套接字 SOCKET sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED); //超时时间 int iTimeout = 3000; //设置接收超时时间 setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeout, sizeof(iTimeout)); //设置发送超时时间 setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*)&iTimeout, sizeof(iTimeout)); //构造ICMP回显请求消息,并以TTL递增的顺序发送报文 //ICMP类型字段 const BYTE ICMP_ECHO_REQUEST = 8; //请求回显 const BYTE ICMP_ECHO_REPLY = 0; //回显应答 const BYTE ICMP_TIMEOUT = 11; //传输超时 //其他常量定义 const int DEF_ICMP_DATA_SIZE = 32; //ICMP报文默认数据字段长度 const int MAX_ICMP_PACKET_SIZE = 1024; //ICMP报文最大长度(包括报头) const DWORD DEF_ICMP_TIMEOUT = 3000; //回显应答超时时间 const int DEF_MAX_HOP = 30; //最大跳站数 //填充ICMP报文中每次发送时不变的字段 char IcmpSendBuf[sizeof(ICMP_HEADER) + DEF_ICMP_DATA_SIZE];//发送缓冲区 memset(IcmpSendBuf, 0, sizeof(IcmpSendBuf)); //初始化发送缓冲区 char IcmpRecvBuf[MAX_ICMP_PACKET_SIZE]; //接收缓冲区 memset(IcmpRecvBuf, 0, sizeof(IcmpRecvBuf)); //初始化接收缓冲区 /*填写ICMP头,回显请求*/ ICMP_HEADER* pIcmpHeader = (ICMP_HEADER*)IcmpSendBuf; pIcmpHeader->type = ICMP_ECHO_REQUEST; pIcmpHeader->code = 0; /*ID字段为当前进程号*/ pIcmpHeader->id = (USHORT)GetCurrentProcessId(); memset(IcmpSendBuf + sizeof(ICMP_HEADER), 'E', DEF_ICMP_DATA_SIZE);//数据字段 USHORT usSeqNo = 0; //ICMP报文序列号 int iTTL = 1; //TTL初始值为1 BOOL bReachDestHost = FALSE; //循环退出标志 int iMaxHot = DEF_MAX_HOP; //循环的最大次数 DECODE_RESULT DecodeResult; //传递给报文解码函数的结构化参数 while (!bReachDestHost && iMaxHot--) { //设置IP报头的TTL字段 setsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char*)&iTTL, sizeof(iTTL)); cout << iTTL << flush; //输出当前序号,flush表示将缓冲区的内容马上送进cout,把输出缓冲区刷新 //填充ICMP报文中每次发送变化的字段 ((ICMP_HEADER*)IcmpSendBuf)->cksum = 0; //校验和先置为0 ((ICMP_HEADER*)IcmpSendBuf)->seq = htons(usSeqNo++); //填充序列号 ((ICMP_HEADER*)IcmpSendBuf)->cksum = checksum((USHORT*)IcmpSendBuf, sizeof(ICMP_HEADER) + DEF_ICMP_DATA_SIZE); //计算校验和 //记录序列号和当前时间 DecodeResult.usSeqNo = ((ICMP_HEADER*)IcmpSendBuf)->seq; //当前序号 DecodeResult.dwRoundTripTime = GetTickCount(); //当前时间 //发送TCP回显请求信息 sendto(sockRaw, IcmpSendBuf, sizeof(IcmpSendBuf), 0, (sockaddr*)&destSockAddr, sizeof(destSockAddr)); //接收ICMP差错报文并进行解析处理 sockaddr_in from; //对端socket地址 int iFromLen = sizeof(from);//地址结构大小 int iReadDataLen; //接收数据长度 while (1) { //接收数据 iReadDataLen = recvfrom(sockRaw, IcmpRecvBuf, MAX_ICMP_PACKET_SIZE, 0, (sockaddr*)&from, &iFromLen); if (iReadDataLen != SOCKET_ERROR)//有数据到达 { //对数据包进行解码 if (DecodeIcmpResponse(IcmpRecvBuf, iReadDataLen, DecodeResult, ICMP_ECHO_REPLY, ICMP_TIMEOUT)) { //到达目的地,退出循环 if (DecodeResult.dwIPaddr.s_addr == destSockAddr.sin_addr.s_addr) bReachDestHost = true; //输出IP地址 cout << 't' << inet_ntoa(DecodeResult.dwIPaddr) << endl; break; } } else if (WSAGetLastError() == WSAETIMEDOUT) //接收超时,输出*号 { cout << " *" << 't' << "Request timed out." << endl; break; } else { break; } } iTTL++; //递增TTL值 }}

ICMP报文会添加一个IP头,然后发到网络当中。

运行结果:

图为,ICMP报文当中的TTL值减为0时,且还没达到目标主机时,对端会回复一个超时报文,结构如下所示:

参考:1:https://blog.csdn.net/u013271921/article/details/45488173

2:https://blog.csdn.net/fuming0210sc/article/details/53521574

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。