1、实验3 ICMP协议实践ping解析资料实验3 ICMP协议实践ping解析计算机网络实验上机指导书专业 班级 学号 姓名 沈阳工程学院信息工程系实验2ICMP协议实践-ping解析一 实验目的掌握ICMP原理,利用其实现网络主机状态测试。二 实验内容 利用ICMP协议原理编程实现PING命令,测试目标主机是否可到达。并了解Ping实现原理。三 实验前的准备 了解ICMP原理及相关概念。 掌握相关软件编程知识。四 实验要求及实验软硬件环境【基本要求】 设计程序完成PING命令。 完成此项实验,完成实验报告。【实验组织方式】 个人实验【实验条件】 局域网环境下微机两台,编程软件。五 实验步骤六
2、.了解ICMP原理以及网络编程(1)源程序:Windows/ Ping.h/#pragma pack(1)#define ICMP_ECHOREPLY 0#define ICMP_ECHOREQ 8/ IP Header - RFC 791typedef struct tagIPHDR u_char VIHL; / Version and IHL u_char TOS; / Type Of Service short TotLen; / Total Length short ID; / Identification short FlagOff; / Flags and Fragment Off
3、set u_char TTL; / Time To Live u_char Protocol; / Protocol u_short Checksum; / Checksum struct in_addr iaSrc; / Internet Address - Source struct in_addr iaDst; / Internet Address - DestinationIPHDR, *PIPHDR;/ ICMP Header - RFC 792typedef struct tagICMPHDR u_char Type; / Type u_char Code; / Code u_sh
4、ort Checksum; / Checksum u_short ID; / Identification u_short Seq; / Sequence char Data; / DataICMPHDR, *PICMPHDR;#define REQ_DATASIZE 32 / Echo Request Data size/ ICMP Echo Requesttypedef struct tagECHOREQUEST ICMPHDR icmpHdr; DWORD dwTime; char cDataREQ_DATASIZE;ECHOREQUEST, *PECHOREQUEST;/ ICMP E
5、cho Replytypedef struct tagECHOREPLY IPHDR ipHdr; ECHOREQUEST echoRequest; char cFiller256;ECHOREPLY, *PECHOREPLY;#pragma pack()/ PING.C - Ping program using ICMP and RAW Sockets/#include #include #include #include ping.h/ Internal Functionsvoid Ping(LPCSTR pstrHost);void ReportError(LPCSTR pstrFrom
6、);int WaitForEchoReply(SOCKET s);u_short in_cksum(u_short *addr, int len);/ ICMP Echo Request/Reply functionsint SendEchoRequest(SOCKET, LPSOCKADDR_IN);DWORD RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);/ main()void main(int argc, char *argv) WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1,1)
7、; int nRet; / Check arguments if (argc != 2) fprintf(stderr,nUsage: ping hostnamen); return; / Init WinSock nRet = WSAStartup(wVersionRequested, &wsaData); if (nRet) fprintf(stderr,nError initializing WinSockn); return; / Check version if (wsaData.wVersion != wVersionRequested) fprintf(stderr,nWinSo
8、ck version not supportedn); return; / Go do the ping Ping(argv1); / Free WinSock WSACleanup();/ Ping()/ Calls SendEchoRequest() and/ RecvEchoReply() and prints resultsvoid Ping(LPCSTR pstrHost) SOCKET rawSocket; LPHOSTENT lpHost; struct sockaddr_in saDest; struct sockaddr_in saSrc; DWORD dwTimeSent;
9、 DWORD dwElapsed; u_char cTTL; int nLoop; int nRet; / Create a Raw socket rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (rawSocket = SOCKET_ERROR) ReportError(socket(); return; / Lookup host lpHost = gethostbyname(pstrHost); if (lpHost = NULL) fprintf(stderr,nHost not found: %sn, pstrHost)
10、; return; / Setup destination socket address saDest.sin_addr.s_addr = *(u_long FAR *) (lpHost-h_addr); saDest.sin_family = AF_INET; saDest.sin_port = 0; / Tell the user what were doing printf(nPinging %s %s with %d bytes of data:n, pstrHost, inet_ntoa(saDest.sin_addr), REQ_DATASIZE); / Ping multiple
11、 times for (nLoop = 0; nLoop 4; nLoop+) / Send ICMP echo request SendEchoRequest(rawSocket, &saDest); / Use select() to wait for data to be received nRet = WaitForEchoReply(rawSocket); if (nRet = SOCKET_ERROR) ReportError(select(); break; if (!nRet) printf(nTimeOut); break; / Receive reply dwTimeSen
12、t = RecvEchoReply(rawSocket, &saSrc, &cTTL); / Calculate elapsed time dwElapsed = GetTickCount() - dwTimeSent; printf(nReply from: %s: bytes=%d time=%ldms TTL=%d, inet_ntoa(saSrc.sin_addr), REQ_DATASIZE, dwElapsed, cTTL); printf(n); nRet = closesocket(rawSocket); if (nRet = SOCKET_ERROR) ReportError
13、(closesocket();/ SendEchoRequest()/ Fill in echo request header/ and send to destinationint SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) static ECHOREQUEST echoReq; static nId = 1; static nSeq = 1; int nRet; / Fill in echo request echoReq.icmpHdr.Type = ICMP_ECHOREQ; echoReq.icmpHdr.Code = 0;
14、echoReq.icmpHdr.Checksum = 0; echoReq.icmpHdr.ID = nId+; echoReq.icmpHdr.Seq = nSeq+; / Fill in some data to send for (nRet = 0; nRet 1 ) sum += *w+; nleft -= 2; /* mop up an odd byte, if necessary */ if( nleft = 1 ) u_short u = 0; *(u_char *)(&u) = *(u_char *)w ; sum += u; /* * add back carry outs
15、from top 16 bits to low 16 bits */ sum = (sum 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum 16); /* add carry */ answer = sum; /* truncate to 16 bits */ return (answer);实验结果如图6-1所示。图6-1 ping程序运行结果(2)LINUX /*简单的ping程序*/#include #include #include #include #include #include #include #incl
16、ude #include #include #include #include #define PACKET_SIZE 4096#define MAX_WAIT_TIME 5#define MAX_NO_PACKETS 3char sendpacketPACKET_SIZE;char recvpacketPACKET_SIZE;int sockfd,datalen=56;int nsend=0,nreceived=0;struct sockaddr_in dest_addr;pid_t pid;struct sockaddr_in from;struct timeval tvrecv;void
17、 statistics(int signo);unsigned short cal_chksum(unsigned short *addr,int len);int pack(int pack_no);void send_packet(void);void recv_packet(void);int unpack(char *buf,int len);void tv_sub(struct timeval *out,struct timeval *in);void statistics(int signo) printf(n-PING statistics-n); printf(%d packe
18、ts transmitted, %d received , %d lostn,nsend,nreceived, (nsend-nreceived)/nsend*100); close(sockfd); exit(1);/*校验和算法*/unsigned short cal_chksum(unsigned short *addr,int len) int nleft=len; int sum=0; unsigned short *w=addr; unsigned short answer=0; /*把ICMP报头二进制数据以2字节为单位累加起来*/ while(nleft1) sum+=*w+;
19、 nleft-=2; /*若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加*/ if( nleft=1) *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; sum=(sum16)+(sum&0xffff); sum+=(sum16); answer=sum; return answer;/*设置ICMP报头*/int pack(int pack_no) int i,packsize; struct icmp *icmp; struct timev
20、al *tval; icmp=(struct icmp*)sendpacket; icmp-icmp_type=ICMP_ECHO; icmp-icmp_code=0; icmp-icmp_cksum=0; icmp-icmp_seq=pack_no; icmp-icmp_id=pid; packsize=8+datalen; tval= (struct timeval *)icmp-icmp_data; gettimeofday(tval,NULL); /*记录发送时间*/ icmp-icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize
21、); /*校验算法*/ return packsize;/*发送三个ICMP报文*/void send_packet() int packetsize; while( nsendMAX_NO_PACKETS) nsend+; packetsize=pack(nsend); /*设置ICMP报头*/ if( sendto(sockfd,sendpacket,packetsize,0, (struct sockaddr *)&dest_addr,sizeof(dest_addr) )0 ) perror(sendto error); continue; sleep(1); /*每隔一秒发送一个ICMP报文*/ /*接收所有ICMP报文*/void recv_packet() int n,fromlen; exte
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1