计算机网络实验五:写一个PING程序
2017-11-07 20:01
351 查看
一、作业要求
1.ping的gui程序
2.作业内要求有可执行的exe,作业链接,Readme,gif图,以及源代码
二、完成步骤
1.创建类型为SOCK_RAW的一个套接字,同时设定协议*IPPROTO_ICMP。
2.创建并初始化ICMP头。
3.调用sendto或WSASendto,将ICMP请求发给远程主机。
4.调用recvfrom或WSARecvfrom,以接收任何ICMP响应。
三、代码实现
四、实现图例
1.
2.
五、程序实现文件链接
http://pan.baidu.com/s/1cdeQKI
六、参考博文
http://blog.sina.com.cn/s/blog_47120f8f0101fjul.html
http://blog.csdn.net/ivy8966/article/details/54612601?locationNum=6&fps=1
http://blog.csdn.net/qq_36249516/article/details/78467009
http://download.csdn.net/download/qq_36249516/10107387
七、总结与体会
由于最近在积极准备软件评测师的考试,所以没能好好静下心来做这次ping程序的实验,大部分借鉴了此次实验其他参与人员的实验流程,希望有机会完成软考资格考试的时候,再来细致地做这个实验,看起来很有意思!
1.ping的gui程序
2.作业内要求有可执行的exe,作业链接,Readme,gif图,以及源代码
二、完成步骤
1.创建类型为SOCK_RAW的一个套接字,同时设定协议*IPPROTO_ICMP。
2.创建并初始化ICMP头。
3.调用sendto或WSASendto,将ICMP请求发给远程主机。
4.调用recvfrom或WSARecvfrom,以接收任何ICMP响应。
三、代码实现
#include <stdio.h> #include <stdlib.h> #include <winsock.h> #pragma comment (lib, "ws2_32.lib") #define ICMP_ECHOREPLY 0 // ICMP回复应答 #define ICMP_ECHOREQ 8 // ICMP回应请求 #define REQ_DATASIZE 32 // 请求数据报大小 // 定义IP首部格式 typedef struct _IPHeader { u_char VIHL; // 版本和首部长度 u_char ToS; // 服务类型 u_short TotalLen; // 总长度 u_short ID; // 标识号 u_short Frag_Flags; // 段偏移量 u_char TTL; // 生存时间 u_char Protocol; // 协议 u_short Checksum; // 首部校验和 struct in_addr SrcIP; // 源IP地址 struct in_addr DestIP; // 目的地址 }IPHDR, *PIPHDR; // 定义ICMP首部格式 typedef struct _ICMPHeader { u_char Type; // 类型 u_char Code; // 代码 u_short Checksum; // 首部校验和 u_short ID; // 标识 u_short Seq; // 序列号 char Data; // 数据 }ICMPHDR, *PICMPHDR; // 定义ICMP回应请求 typedef struct _ECHOREQUEST { ICMPHDR icmpHdr; DWORD dwTime; char cData[REQ_DATASIZE]; }ECHOREQUEST, *PECHOREQUEST; // 定义ICMP回应答复 typedef struct _ECHOREPLY { IPHDR ipHdr; ECHOREQUEST echoRequest; char cFiller[256]; }ECHOREPLY, *PECHOREPLY; // 计算校验和 u_short checksum(u_short *buffer, int len) { register int nleft = len; register u_short *w = buffer; register u_short answer; register int sum = 0; // 使用32bit的累加器,进行16bit的反馈计算 while( nleft > 1 ) { sum += *w++; nleft -= 2; } // 补全奇数位 if( nleft == 1 ) { u_short u = 0; *(u_char *)(&u) = *(u_char *)w ; sum += u; } // 将反馈的16bit从高位移至地位 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return (answer); } // 发送回应请求函数 int SendEchoRequest(SOCKET s,struct sockaddr_in *lpstToAddr) { static ECHOREQUEST echoReq; static nId = 1; static nSeq = 1; int nRet; // 填充回应请求消息 echoReq.icmpHdr.Type = ICMP_ECHOREQ; echoReq.icmpHdr.Code = 0; echoReq.icmpHdr.Checksum = 0; echoReq.icmpHdr.ID = nId++; echoReq.icmpHdr.Seq = nSeq++; // 填充要发送的数据(随便填写) for (nRet = 0; nRet < REQ_DATASIZE; nRet++) echoReq.cData[nRet] = ' '+nRet; // 储存发送的时间 echoReq.dwTime = GetTickCount(); // 计算回应请求的校验和 echoReq.icmpHdr.Checksum = checksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); // 发送回应请求 nRet = sendto(s, // 建立起的套接字 (LPSTR)&echoReq, // 发送的缓冲区内容 sizeof(ECHOREQUEST), 0, // 标志位 (struct sockaddr*)lpstToAddr, // 发送的目标地址 sizeof(SOCKADDR_IN)); // 地址结构长度 if (nRet == SOCKET_ERROR) { printf("sendto() error:%d\n",WSAGetLastError()); } return (nRet); } // 接收应答回复并进行解析 DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) { ECHOREPLY echoReply; int nRet; int nAddrLen = sizeof(struct sockaddr_in); //接收应答回复 nRet = recvfrom(s, // 接收的套接字 (LPSTR)&echoReply, // 接收的缓冲区 sizeof(ECHOREPLY), // 缓冲区长度 0, // 标识 (LPSOCKADDR)lpsaFrom, // 接收的地址 &nAddrLen); // 地址结构长度 // 检验接收结果 if (nRet == SOCKET_ERROR) { printf("recvfrom() error:%d\n",WSAGetLastError()); } // 记录返回的TTL *pTTL = echoReply.ipHdr.TTL; //返回应答时间 return(echoReply.echoRequest.dwTime); } // 等待回应答复,使用select机制 int WaitForEchoReply(SOCKET s) { struct timeval timeout; fd_set readfds; readfds.fd_count = 1; readfds.fd_array[0] = s; timeout.tv_sec = 5; timeout.tv_usec = 0; return(select(1, &readfds, NULL, NULL, &timeout)); } // Ping功能实现 void Ping(char *pstrHost) { SOCKET rawSocket; LPHOSTENT lpHost; struct sockaddr_in destIP; struct sockaddr_in srcIP; DWORD dwTimeSent; DWORD dwElapsed; u_char cTTL; int nLoop; int nRet; // 创建原始套接字,ICMP类型 rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (rawSocket == SOCKET_E ad2e RROR) { printf("socket() error:%d\n",WSAGetLastError()); return; } // 检测目标主机 lpHost = gethostbyname(pstrHost); if (lpHost == NULL) { printf("Host not found: %s\n", pstrHost); return; } // 设置目标机地址 destIP.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr)); destIP.sin_family = AF_INET; destIP.sin_port = 0; // 提示开始进行Ping printf("\nPinging %s with %d bytes of data:\n", inet_ntoa(destIP.sin_addr), REQ_DATASIZE); // 发起多次Ping测试 for (nLoop = 0; nLoop < 4; nLoop++) { //发送ICMP回应请求 SendEchoRequest(rawSocket, &destIP); // 使用select()等待回复的数据 nRet = WaitForEchoReply(rawSocket); if (nRet == SOCKET_ERROR) { printf("select() error:%d\n",WSAGetLastError()); break; } if (!nRet) { printf("\nRequest time out"); break; } //接收回复 dwTimeSent = RecvEchoReply(rawSocket, &srcIP, &cTTL); // 计算花费的时间 dwElapsed = GetTickCount() - dwTimeSent; printf("\nReply from %s: bytes=%d time=%ldms TTL=%d", inet_ntoa(srcIP.sin_addr), REQ_DATASIZE, dwElapsed, cTTL); } printf("\n"); nRet = closesocket(rawSocket); // 关闭套接字,释放资源 if (nRet == SOCKET_ERROR) { printf("closesocket() error:%d\n",WSAGetLastError()); } } void main(int argc, char **argv) { WSADATA wsd; int nRet; // 检测输入的参数 if (argc != 2) { printf("\nUsage: ping hostname\n"); return; } // 初始化Winsock if (WSAStartup(MAKEWORD(1,1), &wsd) != 0) { printf("加载Winsock失败!\n"); } //开始Ping Ping(argv[1]); // 释放Winsock资源 WSACleanup(); }
四、实现图例
1.
2.
五、程序实现文件链接
http://pan.baidu.com/s/1cdeQKI
六、参考博文
http://blog.sina.com.cn/s/blog_47120f8f0101fjul.html
http://blog.csdn.net/ivy8966/article/details/54612601?locationNum=6&fps=1
http://blog.csdn.net/qq_36249516/article/details/78467009
http://download.csdn.net/download/qq_36249516/10107387
七、总结与体会
由于最近在积极准备软件评测师的考试,所以没能好好静下心来做这次ping程序的实验,大部分借鉴了此次实验其他参与人员的实验流程,希望有机会完成软考资格考试的时候,再来细致地做这个实验,看起来很有意思!
相关文章推荐
- 计算机网络(5)-----ICMP协议和PING程序
- 用ping方式探测网络连通性--一个小程序
- 计算机网络实验,JAVA实现一个简单GBN协议,模拟引入数据包的丢失,验证协议的有效性
- 安装程序检测到另外一个程序要求计算机重起 (处理方法)
- 分享一个计算机控制的实验例程
- [网络技巧]一个网线头来测试网络程序
- 实验二:完成一个简单的时间片轮转多道程序内核代码
- 计算机是如何工作的?--通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
- 第一周:通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
- TI CC2530基础实验(GPIO通用I/O中断操作——一个中断处理程序处理一个端口的多个中断)
- pyqt 批量ping一个网段 返回结果 的程序 (加了个界面 效果不理想)
- 开篇词,贴一个刚写的24点牌程序作为实验
- 破解一个网络验证的.NET程序
- 用C语言编写函数实现一个整数计算机,程序接受三个参数,第一个参数为操作项,后两个参数为操作数。
- 计算机网络实验
- JAVA--第九周实验--编写一个模拟用户帐户的程序(内测版)
- 一个计算机爱好者的不完整回忆(四十八)监控优盘的程序
- 好开心,多客户端的一个网络程序终于通了
- qt中采用宽带speex进行网络语音通话实验程序
- 计算机网络实验(转)