Windows系统ping命令的c++实现

news/2025/2/12 15:13:00/
// ping.cpp : 定义控制台应用程序的入口点。
//#include <winsock2.h> 
#include <stdio.h> 
#include <stdlib.h> #define ICMP_ECHO 8 
#define ICMP_ECHOREPLY 0 /* The IP header */ 
typedef struct iphdr 
{ unsigned char h_len:4; // length of the header unsigned char version:4; // Version of IP unsigned char tos; // Type of service unsigned short total_len; // total length of the packet unsigned short ident; // unique identifier unsigned short frag_and_flags; // flags unsigned char ttl; unsigned char proto; // protocol (TCP, UDP etc) unsigned short checksum; // IP checksum unsigned int sourceIP; unsigned int destIP; 
}IpHeader; /* ICMP header */
typedef struct _ihdr 
{ BYTE i_type; BYTE i_code; /* type sub code */USHORT i_cksum; USHORT i_id; USHORT i_seq; /* This is not the std header, but we reserve space for time */ ULONG timestamp; 
}IcmpHeader; #define STATUS_FAILED 0xFFFF 
#define DEF_PACKET_SIZE 32 
#define MAX_PACKET 1024 /* The response is an IP packet. We must decode the IP header to locate the ICMP data */ 
void decode_resp(char *buf, int bytes,struct sockaddr_in *from)
{IpHeader *iphdr; IcmpHeader *icmphdr; unsigned short iphdrlen; iphdr=(IpHeader*)buf; iphdrlen=sizeof(IpHeader)+sizeof(IcmpHeader);if(bytes<iphdrlen) { printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr)); } icmphdr=(IcmpHeader*)(buf+sizeof(IpHeader)); if(icmphdr->i_type!=ICMP_ECHOREPLY) { fprintf(stderr,"non-echo type %d recvd\n",icmphdr->i_type); return; }if(icmphdr->i_id!=(USHORT)GetCurrentProcessId()) { fprintf(stderr,"someone else's packet!\n"); return ; }int correct=0;for(int k=0;k<bytes-iphdrlen;k++){if(*(buf+iphdrlen+k)=='E'){correct++;}}printf("来自 %s 的回复: 字节=%d 时间=%dms TTL=%d\n",\inet_ntoa(from->sin_addr),correct,GetTickCount()-icmphdr->timestamp,iphdr->ttl); 
} USHORT checksum(USHORT *buffer, int size) 
{ unsigned long cksum=0; while(size>1) { cksum+=*buffer++; size-=sizeof(USHORT); } if(size) { cksum+=*(UCHAR*)buffer; } cksum=(cksum>>16)+(cksum&0xffff); cksum+=(cksum>>16); return (USHORT)(~cksum); 
} /* Helper function to fill in various stuff in our ICMP request. */ 
void fill_icmp_data(char *icmp_data, int datasize)
{ char *datapart=NULL; IcmpHeader *icmp_hdr=NULL; icmp_hdr=(IcmpHeader*)icmp_data; icmp_hdr->i_type=ICMP_ECHO; icmp_hdr->i_code=0; icmp_hdr->i_id=(USHORT)GetCurrentProcessId(); icmp_hdr->i_cksum=0; icmp_hdr->i_seq++; icmp_hdr->timestamp=GetTickCount(); datapart=icmp_data+sizeof(IcmpHeader); // Place some junk in the buffer. memset(datapart,'E',datasize-sizeof(IcmpHeader)); icmp_hdr->i_cksum=checksum((USHORT*)icmp_data,datasize);
} int main(int argc, char *argv[])
{ int count=1;int error=-1;int datasize=0; int timeout=3000; struct sockaddr_in addrServer; struct hostent *phostent=NULL; int destlen=sizeof(addrServer); char *dest_ip=NULL; char icmp_data[MAX_PACKET]; char recvbuf[MAX_PACKET]; unsigned int addr=0; char srcIP[MAX_PATH]="0.0.0.0";char dstIP[MAX_PATH]="127.0.0.1";for(int n=1;n<argc;){if(!strcmp(argv[n],"-S")){            n++;strcpy_s(srcIP,argv[n++]);}else if(!strcmp(argv[n],"-n")){n++;count=atoi(argv[n++]);}else{strcpy_s(dstIP,argv[n++]);}}WSADATA wsaData={0}; if(WSAStartup(MAKEWORD(1,1),&wsaData)!=0){ printf("WSA startup error\n"); ExitProcess(STATUS_FAILED); } SOCKET sockClient=WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,0); if(sockClient==INVALID_SOCKET) { printf("WSA socket error\n"); ExitProcess(STATUS_FAILED); } sockaddr_in addrClient;addrClient.sin_addr.S_un.S_addr=inet_addr(srcIP);addrClient.sin_family=AF_INET;addrClient.sin_port=htons(0);error=bind(sockClient,(SOCKADDR *)&addrClient,sizeof(addrClient));if(error){closesocket(sockClient);printf("bind client error\n");return WSACleanup();}unsigned long ul=true;error=ioctlsocket(sockClient,FIONBIO,(unsigned long*)&ul);if(error){closesocket(sockClient);printf("set ioctlsocket error\n");return WSACleanup();}error=setsockopt(sockClient,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout, sizeof(timeout)); if(error==SOCKET_ERROR) { fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } error=setsockopt(sockClient,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout, sizeof(timeout)); if(error==SOCKET_ERROR) { fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } memset(&addrServer,0,sizeof(addrServer)); phostent=gethostbyname(dstIP); if(!phostent){ addr=inet_addr(dstIP); } if((!phostent)&&(addr==INADDR_NONE)) { fprintf(stderr,"Unable to resolve host %s\n",dstIP); ExitProcess(STATUS_FAILED); } if(phostent!=NULL) {memcpy(&(addrServer.sin_addr),phostent->h_addr,phostent->h_length);}else{addrServer.sin_addr.s_addr=addr; }if(phostent) {addrServer.sin_family=phostent->h_addrtype;}else{addrServer.sin_family=AF_INET; dest_ip=inet_ntoa(addrServer.sin_addr);} datasize=DEF_PACKET_SIZE; datasize+=sizeof(IcmpHeader); memset(icmp_data,0,MAX_PACKET);for(int i=0;i<count;i++) {         fill_icmp_data(icmp_data,datasize); int num=sendto(sockClient,icmp_data,datasize,0,(struct sockaddr*)&addrServer, sizeof(addrServer)); if(num==SOCKET_ERROR){ error=WSAGetLastError();if(error==WSAETIMEDOUT) { fprintf(stderr,"errorcode=%d\n",error); continue; }} if(num<datasize) { fprintf(stdout,"Write %d bytes\n",num); }timeval tm;int len=sizeof(int);fd_set set;for(int k=0;k<3;k++){num=recvfrom(sockClient,recvbuf,MAX_PACKET,0,(struct sockaddr*)&addrServer, &destlen); if(num!=SOCKET_ERROR){break;}if(num==SOCKET_ERROR){    Sleep(1);tm.tv_sec=0;        tm.tv_usec=1;        FD_ZERO(&set);        FD_SET(sockClient,&set);        if(select(sockClient,NULL,&set,NULL,&tm)>0)        {            getsockopt(sockClient,SOL_SOCKET,SO_ERROR,(char*)&error,&len);            }                }}if(num!=SOCKET_ERROR){decode_resp(recvbuf,num,&addrServer); }else{printf("Can not find host %s\n",dstIP); }if(i>0){Sleep(1000);}} closesocket(sockClient);WSACleanup();return 0; 
}

编译命令如下:

g++ -std=c++2a -o ping.exe ping.cpp -lws2_32


http://www.ppmy.cn/news/1125950.html

相关文章

Day57:组件库封装-1

封装element组件 参考对象 折叠面板 按钮 npm create vue3 npm i 使用vue3建库如果报错可以尝试禁用vs的 vetur 插件&#xff0c;这是vue2插件&#xff0c;会给vue3项目报错(禁用了之后需要重新加载 src新建components文件夹 下面新建Button文件夹&#xff0c;新建vue&…

Zookeeper高级_选举机制

核心选举原则 Zookeeper集群中只有超过半数以上的服务器启动&#xff0c;集群才能正常工作&#xff1b;在集群正常工作之前&#xff0c;myid小的服务器给myid大的服务器投票&#xff0c;直到集群正常工作&#xff0c;选出Leader&#xff1b;半数机制&#xff1b; 选举机制流程…

ps 去除图标背景色

百度安全验证 https://baijiahao.baidu.com/s?id1766678909759797922&wfrspider&forpc 使用魔术橡皮擦工具&#xff0c;超级简单 最后&#xff0c;保存为PNG格式&#xff0c;因为PNG格式支持透明背景。

从裸机开始安装操作系统

目录 一、预置知识 电脑裸机 win10版本 官方镜像 V.S. 正版系统 二、下载微软官方原版系统镜像 三、使用微PE系统维护U盘 四、安装操作系统 五、总结 一、预置知识 电脑裸机 ●只有硬件部分&#xff0c;还未安装任何软件系统的电脑叫做裸机。 ●主板、硬盘、显卡等必…

利用EXCEL进行XXE攻击

利用EXCEL进行XXE攻击 原因 原因 Microsoft Office从2007版本引入了新的开放的XML文件格式&#xff0c;新的XML文件格式基于压缩的ZIP文件格式规范&#xff0c;由许多部分组成。 我们可以将其解压缩到特定的文件夹中来查看其包含的文件夹和文件&#xff0c;可以发现其中多数是…

上传文件报错:The temporary upload location [/tmp/tomcat/xxx] is not valid

1.上传附加时报错找不到临时目录 Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat/work/Tomcat/localhost/ROOT] is not valid 发生改报错原因为 (1)、SpringBoot项目启动后&#xff0c;系…

Mybatisplus条件构造器

一、Wrapper介绍 Wrapper &#xff1a; 条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper &#xff1a; 用于查询条件封装&#xff0c;生成 sql 的 where 条件 QueryWrapper &#xff1a; 查询条件封装UpdateWrapper &#xff1a; Update 条件封装AbstractLambdaWrapper…

MQ - 31 基础功能: 优先级队列的设计

文章目录 导图概述什么是优先级队列如何设计实现优先级队列业务实现优先级队列的效果内核支持优先级队列RabbitMQ 中优先级队列的实现总结导图 概述 当我们需要在业务中对消息设置优先级,让优先级高的消息能被优先消费,此时就需要用到消息队列中优先级队列的特性。 为了了解…