c/c++写的ping命令

本文介绍了一个使用C/C++和原始套接字编写的ping命令程序,通过ICMP协议进行网络通信。程序包括初始化socket的类、子函数以及主函数,实现了发送和接收ICMP报文,检测网络连通性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前两天写了个小程序,现在给大家分享一下.这个是用c/c++加上原始套接字写的一个ping命令,ping命令的原理想必我不用多说了,了解ICMP协议的朋友们都知道的..
该程序分几个文件:
初始化socket的类:InitSocket.h
/* winsock应用程序必须加载Winsock Dll 
* 加载该Dll的函数就是::WSAStartup() 
* 使用结束后还得释放Dll 用::WSACleanup()函数可以实现 
*/
 
#ifndef _INITSOCKET_H_ 
#define _INITSOCKET_H_ 
#include 
<winsock2.h> 
#include 
<Mswsock.h> 
­
#pragma comment(lib, "WS2_32") 
­
class CInitSocket 

public
CInitSocket(BYTE minorVer 
= 2, BYTE majorVer = 2

  WSADATA wsaData; 
  WORD sockVersion 
= MAKEWORD(minorVer, majorVer); 
  
if (::WSAStartup(sockVersion, &wsaData) != 0
  

   
return
  }
 
}
 
~CInitSocket() 

  ::WSACleanup(); 
}
 
}

#endif //_INITSOCKET_H_ 
­
子函数头文件HdFuns.h 
­
#ifndef _HDFUNS_H_ 
#define _HDFUNS_H_ 
#include 
"InitSocket.h" 
USHORT CheckSum(USHORT 
*buffer, int size); 
BOOL SetTimeout(SOCKET s, 
int nTime, BOOL bRecv); 
#endif //_HDFUNS_H_ 
­
子函数实现文件:HdFuns.cpp 
#include 
"HdFuns.h" 
#include 
"Ws2tcpip.h" 
#include 
<winsock2.h> 
//校验和计算 
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); 
}
 
设置套接字超时时间 
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; 
}
 
­
主函数:main.cpp 
#include 
<iostream> 
#include 
"HdFuns.h" 
#include 
<windows.h> 
#include 
<stdio.h> 
­
using namespace std; 
­
CInitSocket initSocket; 
#define PROTO_ICMP    1 
#define PROTO_IGMP    2 
#define PROTO_TCP     6 
#define PROTO_UDP     17 
typedef 
struct _IPHeader  // 20字节的IP头 

    UCHAR     iphVerLen;      
// 版本号和头长度(各占4位) 
    UCHAR     ipTOS;          // 服务类型 
    USHORT   ipLength;       // 封包总长度,即整个IP报的长度 
    USHORT   ipID;     // 封包标识,惟一标识发送的每一个数据报 
    USHORT   ipFlags;       // 标志 
    UCHAR     ipTTL;       // 生存时间,就是TTL 
    UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等 
    USHORT   ipChecksum;     // 校验和 
    ULONG     ipSource;       // 源IP地址 
    ULONG     ipDestination;  // 目标IP地址 
}
 IPHeader, *PIPHeader; 
­
typedef 
struct icmp_hdr 

unsigned 
char icmp_type; 
unsigned 
char icmp_code; 
unsigned 
short icmp_checksum; 
unsigned 
short icmp_id; 
unsigned 
short icmp_sequence; 
int icmp_timestamp; 
}
ICMP_HDR, *PICMP_HDR; 
­
int main(void

char szDest[50] ;//目标IP 
­
while(true

  cout
<<"IP: "
  cin
>>szDest; 
  SOCKET sRaw 
= ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);//原始套接字创建 
  SetTimeout(sRaw, 1000, TRUE);//设置超时 
­
  
//目标地址 
  SOCKADDR_IN dest; 
  dest.sin_port 
= ::htons(0); 
  dest.sin_addr.S_un.S_addr 
= ::inet_addr(szDest); 
  dest.sin_family 
= AF_INET; 
  
char buffer[sizeof(ICMP_HDR) + 1024]; 
  ICMP_HDR 
*pIcmp = (ICMP_HDR *)buffer; 
  pIcmp
->icmp_type = 8
  pIcmp
->icmp_code = 0
  pIcmp
->icmp_id = ::GetCurrentProcessId(); 
  pIcmp
->icmp_sequence = 0
  pIcmp
->icmp_checksum = 0
  
//填充数据域 
  ::memset(&buffer[sizeof(ICMP_HDR)], 'E'32); 
­
  USHORT nSeq 
= 0
  
char recvBuf[1024]; 
  SOCKADDR_IN from; 
  
int nLen = sizeof(from); 
­
  
for (int i = 0; i < 4; i++
  

   
int nRet; 
   pIcmp
->icmp_checksum = 0
   pIcmp
->icmp_timestamp = ::GetTickCount(); 
   pIcmp
->icmp_sequence = nSeq++
   pIcmp
->icmp_checksum = CheckSum((USHORT *)buffer, sizeof(ICMP_HDR) + 32); 
   
   
//发送请求回显的ICMP报文 
   nRet = ::sendto(sRaw, buffer, sizeof(ICMP_HDR) + 320, (SOCKADDR *)&dest, sizeof(dest)); 
   
if (nRet == SOCKET_ERROR) 
   

    cout
<<"SendTo Failed: "<<::WSAGetLastError()<<endl; 
    
continue
   }
 
   
   
//接受回显报文 
   nRet = ::recvfrom(sRaw, recvBuf, 10240, (sockaddr *)&from, &nLen); 
   
if (nRet == SOCKET_ERROR) 
   

    cout
<<"Request timed out!!"<<endl; 
    
continue
   }
 
   
int nTick = ::GetTickCount(); 
   
if (nRet < sizeof(IPHeader) + sizeof(ICMP_HDR)) 
   

    cout
<<"too few bytes!"<<endl; 
   }
 
   PICMP_HDR pRecvIcmp 
= (PICMP_HDR)(recvBuf  + sizeof(IPHeader)); 
   PIPHeader pRecvIP 
= (PIPHeader)(recvBuf); 
   
   
if (pRecvIcmp->icmp_type != 0
   

    cout
<<"nonecho type "<<pRecvIcmp->icmp_type<<"recved"<<endl; 
    
continue
   }
 
   
if (pRecvIcmp->icmp_id != ::GetCurrentProcessId()) 
   

    cout
<<"someone else's packet!"<<endl; 
    
continue
   }
 
   
//报文分析 
   cout<<nRet<<"bytes from "<<inet_ntoa(from.sin_addr)<<" "
   cout
<<"icmp_seq = "<<pRecvIcmp->icmp_sequence<<" "
   cout
<<"time = "<<(nTick - pRecvIcmp->icmp_timestamp)<<"ms"<<endl; 
   ::Sleep(
1000); 
  }
 
}
 
return 0
}
以下是执行结果:
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值