1、实验3ICMP协议实践ping解析计算机网络实验上机指导书专业 班级 学号 姓名 沈阳工程学院信息工程系实验2ICMP协议实践-ping解析一 实验目的掌握ICMP原理,利用其实现网络主机状态测试。二 实验内容 利用ICMP协议原理编程实现PING命令,测试目标主机是否可到达。并了解Ping实现原理。三 实验前的准备 了解ICMP原理及相关概念。 掌握相关软件编程知识。四 实验要求及实验软硬件环境【基本要求】 设计程序完成PING命令。 完成此项实验,完成实验报告。【实验组织方式】 个人实验【实验条件】 局域网环境下微机两台,编程软件。五 实验步骤.了解ICMP原理以及网络编程(1)源程序:W
2、indows/ 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 Offset u_char TTL; / Time
3、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_short Checksum; / Checksu
4、m 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 Echo Replytypedef struct
5、 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);int WaitForEchoReply(
6、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); int nRet; / Check arg
7、uments 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,nWinSock version not supporte
8、dn); 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; DWORD dwElapsed; u_cha
9、r 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); return; / Setup desti
10、nation 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 times for (nLoop = 0;
11、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 dwTimeSent = RecvEchoReply(rawSo
12、cket, &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(closesocket();/ SendEc
13、hoRequest()/ 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; echoReq.icmpHdr.Checksu
14、m = 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 from top 16 bits to low
15、 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 #include #include #include #
16、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 statistics(int signo);
17、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 packets transmitted, %d rece
18、ived , %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+; nleft-=2; /*若ICMP报头为奇数
19、个字节,会剩下最后一字节。把最后一个字节视为一个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 timeval *tval; icmp=(struct
20、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); /*校验算法*/ return pack
21、size;/*发送三个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; extern int errno; signal(SIGALR
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1