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


    1. // ping.cpp : 定义控制台应用程序的入口点。
    2. //
    3. #include
    4. #include
    5. #include
    6. #define ICMP_ECHO 8
    7. #define ICMP_ECHOREPLY 0
    8. /* The IP header */
    9. typedef struct iphdr
    10. {
    11. unsigned char h_len:4; // length of the header
    12. unsigned char version:4; // Version of IP
    13. unsigned char tos; // Type of service
    14. unsigned short total_len; // total length of the packet
    15. unsigned short ident; // unique identifier
    16. unsigned short frag_and_flags; // flags
    17. unsigned char ttl;
    18. unsigned char proto; // protocol (TCP, UDP etc)
    19. unsigned short checksum; // IP checksum
    20. unsigned int sourceIP;
    21. unsigned int destIP;
    22. }IpHeader;
    23. /* ICMP header */
    24. typedef struct _ihdr
    25. {
    26. BYTE i_type;
    27. BYTE i_code; /* type sub code */
    28. USHORT i_cksum;
    29. USHORT i_id;
    30. USHORT i_seq; /* This is not the std header, but we reserve space for time */
    31. ULONG timestamp;
    32. }IcmpHeader;
    33. #define STATUS_FAILED 0xFFFF
    34. #define DEF_PACKET_SIZE 32
    35. #define MAX_PACKET 1024
    36. /* The response is an IP packet. We must decode the IP header to locate the ICMP data */
    37. void decode_resp(char *buf, int bytes,struct sockaddr_in *from)
    38. {
    39. IpHeader *iphdr;
    40. IcmpHeader *icmphdr;
    41. unsigned short iphdrlen;
    42. iphdr=(IpHeader*)buf;
    43. iphdrlen=sizeof(IpHeader)+sizeof(IcmpHeader);
    44. if(bytes
    45. {
    46. printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));
    47. }
    48. icmphdr=(IcmpHeader*)(buf+sizeof(IpHeader));
    49. if(icmphdr->i_type!=ICMP_ECHOREPLY)
    50. {
    51. fprintf(stderr,"non-echo type %d recvd\n",icmphdr->i_type); return;
    52. }
    53. if(icmphdr->i_id!=(USHORT)GetCurrentProcessId())
    54. {
    55. fprintf(stderr,"someone else's packet!\n"); return ;
    56. }
    57. int correct=0;
    58. for(int k=0;k
    59. {
    60. if(*(buf+iphdrlen+k)=='E')
    61. {
    62. correct++;
    63. }
    64. }
    65. printf("来自 %s 的回复: 字节=%d 时间=%dms TTL=%d\n",\
    66. inet_ntoa(from->sin_addr),correct,GetTickCount()-icmphdr->timestamp,iphdr->ttl);
    67. }
    68. USHORT checksum(USHORT *buffer, int size)
    69. {
    70. unsigned long cksum=0;
    71. while(size>1)
    72. {
    73. cksum+=*buffer++;
    74. size-=sizeof(USHORT);
    75. }
    76. if(size)
    77. {
    78. cksum+=*(UCHAR*)buffer;
    79. }
    80. cksum=(cksum>>16)+(cksum&0xffff);
    81. cksum+=(cksum>>16);
    82. return (USHORT)(~cksum);
    83. }
    84. /* Helper function to fill in various stuff in our ICMP request. */
    85. void fill_icmp_data(char *icmp_data, int datasize)
    86. {
    87. char *datapart=NULL;
    88. IcmpHeader *icmp_hdr=NULL;
    89. icmp_hdr=(IcmpHeader*)icmp_data;
    90. icmp_hdr->i_type=ICMP_ECHO;
    91. icmp_hdr->i_code=0;
    92. icmp_hdr->i_id=(USHORT)GetCurrentProcessId();
    93. icmp_hdr->i_cksum=0;
    94. icmp_hdr->i_seq++;
    95. icmp_hdr->timestamp=GetTickCount();
    96. datapart=icmp_data+sizeof(IcmpHeader); // Place some junk in the buffer.
    97. memset(datapart,'E',datasize-sizeof(IcmpHeader));
    98. icmp_hdr->i_cksum=checksum((USHORT*)icmp_data,datasize);
    99. }
    100. int main(int argc, char *argv[])
    101. {
    102. int count=1;
    103. int error=-1;
    104. int datasize=0;
    105. int timeout=3000;
    106. struct sockaddr_in addrServer;
    107. struct hostent *phostent=NULL;
    108. int destlen=sizeof(addrServer);
    109. char *dest_ip=NULL;
    110. char icmp_data[MAX_PACKET];
    111. char recvbuf[MAX_PACKET];
    112. unsigned int addr=0;
    113. char srcIP[MAX_PATH]="0.0.0.0";
    114. char dstIP[MAX_PATH]="127.0.0.1";
    115. for(int n=1;n
    116. {
    117. if(!strcmp(argv[n],"-S"))
    118. {
    119. n++;strcpy_s(srcIP,argv[n++]);
    120. }
    121. else if(!strcmp(argv[n],"-n"))
    122. {
    123. n++;count=atoi(argv[n++]);
    124. }
    125. else
    126. {
    127. strcpy_s(dstIP,argv[n++]);
    128. }
    129. }
    130. WSADATA wsaData={0};
    131. if(WSAStartup(MAKEWORD(1,1),&wsaData)!=0)
    132. {
    133. printf("WSA startup error\n");
    134. ExitProcess(STATUS_FAILED);
    135. }
    136. SOCKET sockClient=WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,0);
    137. if(sockClient==INVALID_SOCKET)
    138. {
    139. printf("WSA socket error\n");
    140. ExitProcess(STATUS_FAILED);
    141. }
    142. sockaddr_in addrClient;
    143. addrClient.sin_addr.S_un.S_addr=inet_addr(srcIP);
    144. addrClient.sin_family=AF_INET;
    145. addrClient.sin_port=htons(0);
    146. error=bind(sockClient,(SOCKADDR *)&addrClient,sizeof(addrClient));
    147. if(error)
    148. {
    149. closesocket(sockClient);
    150. printf("bind client error\n");
    151. return WSACleanup();
    152. }
    153. unsigned long ul=true;
    154. error=ioctlsocket(sockClient,FIONBIO,(unsigned long*)&ul);
    155. if(error)
    156. {
    157. closesocket(sockClient);
    158. printf("set ioctlsocket error\n");
    159. return WSACleanup();
    160. }
    161. error=setsockopt(sockClient,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout, sizeof(timeout));
    162. if(error==SOCKET_ERROR)
    163. {
    164. fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError());
    165. ExitProcess(STATUS_FAILED);
    166. }
    167. error=setsockopt(sockClient,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout, sizeof(timeout));
    168. if(error==SOCKET_ERROR)
    169. {
    170. fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError());
    171. ExitProcess(STATUS_FAILED);
    172. }
    173. memset(&addrServer,0,sizeof(addrServer));
    174. phostent=gethostbyname(dstIP);
    175. if(!phostent)
    176. {
    177. addr=inet_addr(dstIP);
    178. }
    179. if((!phostent)&&(addr==INADDR_NONE))
    180. {
    181. fprintf(stderr,"Unable to resolve host %s\n",dstIP);
    182. ExitProcess(STATUS_FAILED);
    183. }
    184. if(phostent!=NULL)
    185. {
    186. memcpy(&(addrServer.sin_addr),phostent->h_addr,phostent->h_length);
    187. }
    188. else
    189. {
    190. addrServer.sin_addr.s_addr=addr;
    191. }
    192. if(phostent)
    193. {
    194. addrServer.sin_family=phostent->h_addrtype;
    195. }
    196. else
    197. {
    198. addrServer.sin_family=AF_INET;
    199. dest_ip=inet_ntoa(addrServer.sin_addr);
    200. }
    201. datasize=DEF_PACKET_SIZE;
    202. datasize+=sizeof(IcmpHeader);
    203. memset(icmp_data,0,MAX_PACKET);
    204. for(int i=0;i
    205. {
    206. fill_icmp_data(icmp_data,datasize);
    207. int num=sendto(sockClient,icmp_data,datasize,0,(struct sockaddr*)&addrServer, sizeof(addrServer));
    208. if(num==SOCKET_ERROR)
    209. {
    210. error=WSAGetLastError();
    211. if(error==WSAETIMEDOUT)
    212. {
    213. fprintf(stderr,"errorcode=%d\n",error);
    214. continue;
    215. }
    216. }
    217. if(num
    218. {
    219. fprintf(stdout,"Write %d bytes\n",num);
    220. }
    221. timeval tm;
    222. int len=sizeof(int);
    223. fd_set set;
    224. for(int k=0;k<3;k++)
    225. {
    226. num=recvfrom(sockClient,recvbuf,MAX_PACKET,0,(struct sockaddr*)&addrServer, &destlen);
    227. if(num!=SOCKET_ERROR)
    228. {
    229. break;
    230. }
    231. if(num==SOCKET_ERROR)
    232. {
    233. Sleep(1);
    234. tm.tv_sec=0;
    235. tm.tv_usec=1;
    236. FD_ZERO(&set);
    237. FD_SET(sockClient,&set);
    238. if(select(sockClient,NULL,&set,NULL,&tm)>0)
    239. {
    240. getsockopt(sockClient,SOL_SOCKET,SO_ERROR,(char*)&error,&len);
    241. }
    242. }
    243. }
    244. if(num!=SOCKET_ERROR)
    245. {
    246. decode_resp(recvbuf,num,&addrServer);
    247. }
    248. else
    249. {
    250. printf("Can not find host %s\n",dstIP);
    251. }
    252. if(i>0)
    253. {
    254. Sleep(1000);
    255. }
    256. }
    257. closesocket(sockClient);
    258. WSACleanup();
    259. return 0;
    260. }

    编译命令如下:

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

  • 相关阅读:
    神经网络处理器设计原理,神经网络控制系统设计
    SCRUM产品负责人(CSPO)认证培训课程
    JSON数据和解析
    docker打包部署自己的应用
    Sentinel整合OpenFeign
    【Vue】Router 方法使用
    git 查漏补缺
    [C++](8)模板的初步了解
    justjavac:从辍学到成为Deno核心代码贡献者,我的十年编程生涯
    python3 交叉编译环境搭建
  • 原文地址:https://blog.csdn.net/princewwj/article/details/133302486