网络程序设计——ping命令的实现
来源:互联网 发布:亨廷顿 谈中国知乎 编辑:程序博客网 时间:2024/05/22 05:12
注意:ping命令采用ICMP协议,因此创建的socket参数为SOCK_RAW,这个是需要管理员身份才能创建的,因此编译成功后对生成的可执行文件采用管理员身份运行!!!!不然会创建socket失败的!!!!
代码中包含自己头文件见:
http://blog.csdn.net/jianxia_wzx/article/details/8515585
comm.cpp
//////////////////////////////////////////////////// comm.cpp文件#include <winsock2.h>#include <windows.h>#include "Ws2tcpip.h"#include "comm.h"USHORT checksum(USHORT* buff, int size){unsigned long cksum = 0;while(size>1){cksum += *buff++;size -= sizeof(USHORT);}// 是奇数if(size){cksum += *(UCHAR*)buff;}// 将32位的chsum高16位和低16位相加,然后取反cksum = (cksum >> 16) + (cksum & 0xffff);cksum += (cksum >> 16);// ???return (USHORT)(~cksum);}BOOL SetTTL(SOCKET s, int nValue){int ret = ::setsockopt(s, IPPROTO_IP, IP_TTL, (char*)&nValue, sizeof(nValue));return ret != SOCKET_ERROR;}BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv){int ret = ::setsockopt(s, SOL_SOCKET, bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));return ret != SOCKET_ERROR;}
ping.cpp
///////////////////////////////////////////// ping.cpp文件#include "../common/initsock.h"#include "../common/protoinfo.h"#include "../common/comm.h"#include <stdio.h>CInitSock theSock;typedef struct icmp_hdr{ unsigned char icmp_type;// 消息类型 unsigned char icmp_code;// 代码 unsigned short icmp_checksum;// 校验和// 下面是回显头 unsigned short icmp_id;// 用来惟一标识此请求的ID号,通常设置为进程ID unsigned short icmp_sequence;// 序列号 unsigned long icmp_timestamp; // 时间戳} ICMP_HDR, *PICMP_HDR;int main(){// 目的IP地址,即要Ping的IP地址char szDestIp[] = "127.0.0.1";// 127.0.0.1// 创建原始套节字SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);if(INVALID_SOCKET==sRaw){printf("socket()Failed:%d\n",WSAGetLastError());return -1;}// 设置接收超时SetTimeout(sRaw, 1000, TRUE);// 设置目的地址SOCKADDR_IN dest;dest.sin_family = AF_INET;dest.sin_port = htons(0);dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);// 创建ICMP封包char buff[sizeof(ICMP_HDR) + 32];ICMP_HDR* pIcmp = (ICMP_HDR*)buff;// 填写ICMP封包数据pIcmp->icmp_type = 8;// 请求一个ICMP回显pIcmp->icmp_code = 0;pIcmp->icmp_id = (USHORT)::GetCurrentProcessId();pIcmp->icmp_checksum = 0;pIcmp->icmp_sequence = 0;// 填充数据部分,可以为任意memset(&buff[sizeof(ICMP_HDR)], 'E', 32);// 开始发送和接收ICMP封包USHORTnSeq = 0;char recvBuf[1024];SOCKADDR_IN from;int nLen = sizeof(from);while(TRUE){static int nCount = 0;int nRet;if(nCount++ == 4)break;pIcmp->icmp_checksum = 0;pIcmp->icmp_timestamp = ::GetTickCount();pIcmp->icmp_sequence = nSeq++;pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);//nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));if(nRet == SOCKET_ERROR){printf(" sendto() failed: %d \n", ::WSAGetLastError());return -1;}nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);if(nRet == SOCKET_ERROR){if(::WSAGetLastError() == WSAETIMEDOUT){printf(" timed out\n");continue;}printf(" recvfrom() failed: %d\n", ::WSAGetLastError());return -1;}// 下面开始解析接收到的ICMP封包int nTick = ::GetTickCount();if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR)){printf(" Too few bytes from %s \n", ::inet_ntoa(from.sin_addr));}// 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); // (ICMP_HDR*)(recvBuf + sizeof(IPHeader));if(pRecvIcmp->icmp_type != 0)// 回显{printf(" nonecho type %d recvd \n", pRecvIcmp->icmp_type);return -1;}if(pRecvIcmp->icmp_id != ::GetCurrentProcessId()){printf(" someone else's packet! \n");return -1;}printf(" %d bytes from %s:", nRet, inet_ntoa(from.sin_addr));printf(" icmp_seq = %d. ", pRecvIcmp->icmp_sequence);printf(" time: %d ms", nTick - pRecvIcmp->icmp_timestamp);printf(" \n");::Sleep(1000);} getchar();return 0;}
结果如下:
- 网络程序设计——ping命令的实现
- ping 命令的实现
- ping命令的实现
- ping 命令的实现
- ping命令的实现
- ping命令的实现
- ping命令的C实现
- Socket网络程序设计(3) ———— 利用tcp完成文件传输的设计和实现
- Socket网络程序设计(4) ———— 实现linux和windows的文件传输
- C# ping命令的实现方法:Ping类的使用
- C# ping命令的实现方法:Ping类的使用
- 16、Ping的实现原理,ping 命令格式。
- 【二十五】 Linux网络编程——模仿Ping命令的实现
- Ping命令原来是这样实现的
- Ping命令原来是这样实现的
- linux ping 命令的实现和分析
- linux下ping命令的实现源码
- android中ping命令的实现
- 实现顺序队列各种基本运算的算法
- 一句话搞定Frame局中,不必要获取屏幕大小
- 51中断
- C语言数据类型
- Codeforces #163 Div2 E
- 网络程序设计——ping命令的实现
- 实现顺序队列各种基本运算的算法
- linux 获取时间差
- 教你如何训练和提高自己的情商
- UML 概述
- Python入门解析篇
- 荷叶茶的制作
- AMPS:内存管理模块源码解读(二)
- Python多线程实例