技术专栏
linux下ping命令的c++实现
一 原理
ping命令工作在ip层,在程序中通过raw scket进行数据的收发,发数据时不需要填充ip头部,但是在接收数据时需要过滤掉ip头部信息。icmp头部重要的字段有三 个,type,code,checksum,其中type表示命令的类型,对于ping命令来说,type的值为8表示发送icmp,type值为0表示 是icmp的回包,code表示type下的子命令,对于ping命令来说,code的值为0。checksum字段表示icmp包的校验字段,校验方法 为对icmp的所有字段取和再取反码。
二 实现代码:
ping.h
#ifndef __SAM_PING_
#define __SAM_PING_
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "fcntl.h"
#include "errno.h"
#include "signal.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "sys/time.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "netdb.h"
#define MAXBUFFLEN 200
#define ICMP_ECHO 8 /* icmp echo requir */
#define ICMP_ECHOREPLY 0 /* icmp echo reply */
#define ICMP_HEADSIZE 8 /* icmp packet header size */
#define IP_HEADSIZE 20 /* ip packet header size */
#pragma pack(1)
typedef struct tagIpHead /* icmp packet header */
{
u_char ip_verlen; /* ip version and ip header lenth*/
u_char ip_tos; /* ip type of service */
u_short ip_len; /* ip packet lenghth */
u_short ip_id; /* ip packet identification */
u_short ip_fragoff; /* ip packet fragment and offset */
u_char ip_ttl; /* ip packet time to live */
u_char ip_proto; /* ip packet protocol type */
u_short ip_chksum; /* ip packet header checksum */
u_long ip_src_addr; /* ip source ip adress */
u_long ip_dst_addr; /* ip destination ip adress */
} IPHEAD;
typedef struct tagIcmpHead /* icmp header */
{
u_char icmp_type; /* icmp service type */
/* 8 echo require, 0 echo reply */
u_char icmp_code; /* icmp header code */
u_short icmp_chksum; /* icmp header chksum */
u_short icmp_id; /* icmp packet identification */
u_short icmp_seq; /* icmp packet sequent */
u_char icmp_data[1]; /* icmp data, use as pointer */
} ICMPHEAD;
#pragma pack()
class CICMP
{
private:
int m_iSocket;
int m_iPkgSize;
long m_iSendTime; /*发送ping包的时间戳*/
long m_iRecvTime; /*接收ping包的时间戳*/
long m_iDelay;
IPHEAD m_stIpHead;
ICMPHEAD m_stIcmpHead;
char m_szIcmpData[MAXBUFFLEN];
protected:
long TimeNow();
bool validChkSum(ushort* buffer,int size);
u_short ChkSum(u_short* pIcmpData,int iDataLen);
int ParseRecv(IPHEAD* pHeader,int size);
public:
CICMP(int pkgSize = 0):m_iPkgSize(pkgSize){memset(m_szIcmpData,0,MAXBUFFLEN);}
int CreateRawSocket();
int Ping(const char* szIp,int pkgSize);
int Stat();
int Receive();
};
#endif
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
<
ping.cpp
#include "ping.h"
#include <iostream>
#include <string>
using namespace std;
u_short CICMP::ChkSum( u_short * buffer, int size )
/* for check sum of icmp header */
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size-=sizeof(unsigned short);
}
if(size) cksum+=*(unsigned short*)buffer;
cksum=(cksum >> 16)+(cksum&0xffff);
cksum+=(cksum >>16);
return (unsigned short)(~cksum);
}
bool CICMP::validChkSum(unsigned short *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size-=sizeof(unsigned short);
}
if(size) cksum+=*(unsigned short*)buffer;
cksum=(cksum >> 16)+(cksum&0xffff);
cksum+=(cksum >>16);
return ((unsigned short)cksum == 0xFFFF);
}
int CICMP::CreateRawSocket()
{
this->m_iSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(this->m_iSocket < 0)
{
perror("socket");
return -1;
}
return 0;
}
long CICMP::TimeNow()
{
struct timeval now;
long lPassed;
gettimeofday(&now, 0);
lPassed = now.tv_sec * 1000000 + now.tv_usec;
/* now.tv_sec in second */
/* now.tv_usec in 1/1000000 second */
return lPassed;
}
int CICMP::Ping(const char* szIp,int pkgSize)
{
struct sockaddr_in descAddr;
bzero(&descAddr, sizeof(descAddr));
descAddr.sin_family = AF_INET;
u_long lHostIp;
struct hostent* h = NULL;
/* check host format */
if ( ( lHostIp = inet_addr(szIp) ) != INADDR_NONE )
{
/* is available ip adress */
//cout << "is available ip address" << endl;
descAddr.sin_addr.s_addr = lHostIp;
}
else if ( h = gethostbyname(szIp))
{
/* is available host name */
/* from hosts file of local host */
/* or from DNS */
//cout << "is available host name" << endl;
bcopy(h->h_addr, &descAddr.sin_addr, h->h_length);
}
else
{
/* bad ip adress or host name */
/* exit */
fprintf( stderr, "bad IP or host\n" );
return -1;
}
cout << "ping " << szIp<< endl;
//begin Ping
int iPacketSize = 0;
char* buf = new char[MAXBUFFLEN];
memset(buf,0,MAXBUFFLEN);
/* make the icmp header information */
ICMPHEAD *pIcmpHead = (ICMPHEAD *)buf;
pIcmpHead->icmp_type = ICMP_ECHO;
pIcmpHead->icmp_code = 0;
pIcmpHead->icmp_id = 1;
pIcmpHead->icmp_seq = 1;
pIcmpHead->icmp_chksum = 0;
/* store time information as icmp packet content, 4 bytes */
/* u may store other information instead */
*((long *)pIcmpHead->icmp_data) = TimeNow();
this->m_iSendTime = TimeNow();
//iPacketSize = ICMP_HEADSIZE + 4; /* icmp packet length */
iPacketSize = sizeof(ICMPHEAD) + 3;
/* icmp header check sum */
pIcmpHead->icmp_chksum = this->ChkSum((u_short *)pIcmpHead, iPacketSize );
/* remember the time when send for calculate round trip time */
//lSendTime = time_now();
/* send the icmp packet to des host */
//cout << "send pkg size " << iPacketSize << endl;
if (sendto(m_iSocket, buf, iPacketSize, 0, (struct sockaddr *)&descAddr, sizeof(descAddr) ) < 0)
{
perror("send failed");
delete [] buf;
return -1;
}
delete [] buf;
//usleep(0);
return 0;
}
int CICMP::Receive()
{
struct sockaddr_in fromAddr;
int size = 0;
char* buf = new char[MAXBUFFLEN];
memset(buf,0,MAXBUFFLEN);
int namelen = sizeof(fromAddr);
//cout << "before recvfrom" << endl;
size = recvfrom(this->m_iSocket,buf,MAXBUFFLEN - 1,0,(struct sockaddr *)&fromAddr,(socklen_t*)&namelen);
if(size == -1)
{
cout << "recv ping back failed:" << strerror(errno) << endl;
return -1;
}
IPHEAD* pIpHead = (IPHEAD *)buf;
//cout << "after recvfrom:" << size << endl;
/* get the ip packet lenth */
/* if too small, not the icmp echoreply packet */
/* give it up */
int iIpHeadLen = (int)((pIpHead->ip_verlen & 0x0f) << 2);
if (size < iIpHeadLen + ICMP_HEADSIZE)
{
cout << "recv header is too short,give it up" << endl;
delete buf;
return -1;
}
//int ttl = pIpHead->ip_ttl; /* time to live param */
/* get the icmp header information */
ICMPHEAD *pIcmpHead = (ICMPHEAD *)(buf + iIpHeadLen);
/* not icmp echo reply packet, give it up */
if (pIcmpHead->icmp_type != ICMP_ECHOREPLY)
{
cout << "recv pkg not ICMP reply,give it up" << endl;
delete buf;
return -1;
}
/* not proper icmp sequent number, give it up */
if (pIcmpHead->icmp_id != 1 || pIcmpHead->icmp_seq != 1)
{
cout << "icmp header's id and seq error" << endl;
delete buf;
return -1;
}
long iCurTime = this->TimeNow();
this->m_iRecvTime = iCurTime;
ParseRecv((IPHEAD *)buf,size);
delete buf;
return 0;
}
int CICMP::ParseRecv(IPHEAD * pHeader,int size)
{
memcpy(&m_stIpHead,pHeader,sizeof(IPHEAD));
char* szTmp = (char*)pHeader;
char* ptrIcmp = szTmp + sizeof(IPHEAD);
memcpy(&m_stIcmpHead,ptrIcmp,sizeof(ICMPHEAD));
/* get the data of icmp*/
szTmp += sizeof(ICMPHEAD) - 1;
int iDataLen = size - sizeof(IPHEAD) - sizeof(ICMPHEAD) + 1;
memcpy(m_szIcmpData,szTmp,iDataLen);
return 0;
}
int CICMP::Stat()
{
struct in_addr recvFrom;
memcpy(&recvFrom,&m_stIpHead.ip_src_addr,4);
u_char ipTTL = this->m_stIpHead.ip_ttl;
//int iSendTime = atoi(this->m_szIcmpData);
int iDelayTime = (int)((m_iRecvTime - m_iSendTime)/1000);
char szBuff[100] = {0};
char* szIp = inet_ntoa(recvFrom);
if(szIp == NULL)
{
cout << "get src ip failed" << endl;
return -1;
}
sprintf(szBuff,"recv from %s,delay=%ds,TTL=%d",szIp,iDelayTime,ipTTL);
cout << szBuff << endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
<
#ifndef __SAM_PING_
#define __SAM_PING_
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "fcntl.h"
#include "errno.h"
#include "signal.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "sys/time.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "netdb.h"
#define MAXBUFFLEN 200
#define ICMP_ECHO 8 /* icmp echo requir */
#define ICMP_ECHOREPLY 0 /* icmp echo reply */
#define ICMP_HEADSIZE 8 /* icmp packet header size */
#define IP_HEADSIZE 20 /* ip packet header size */
#pragma pack(1)
typedef struct tagIpHead /* icmp packet header */
{
u_char ip_verlen; /* ip version and ip header lenth*/
u_char ip_tos; /* ip type of service */
u_short ip_len; /* ip packet lenghth */
u_short ip_id; /* ip packet identification */
u_short ip_fragoff; /* ip packet fragment and offset */
u_char ip_ttl; /* ip packet time to live */
u_char ip_proto; /* ip packet protocol type */
u_short ip_chksum; /* ip packet header checksum */
u_long ip_src_addr; /* ip source ip adress */
u_long ip_dst_addr; /* ip destination ip adress */
} IPHEAD;
typedef struct tagIcmpHead /* icmp header */
{
u_char icmp_type; /* icmp service type */
/* 8 echo require, 0 echo reply */
u_char icmp_code; /* icmp header code */
u_short icmp_chksum; /* icmp header chksum */
u_short icmp_id; /* icmp packet identification */
u_short icmp_seq; /* icmp packet sequent */
u_char icmp_data[1]; /* icmp data, use as pointer */
} ICMPHEAD;
#pragma pack()
class CICMP
{
private:
int m_iSocket;
int m_iPkgSize;
long m_iSendTime; /*发送ping包的时间戳*/
long m_iRecvTime; /*接收ping包的时间戳*/
long m_iDelay;
IPHEAD m_stIpHead;
ICMPHEAD m_stIcmpHead;
char m_szIcmpData[MAXBUFFLEN];
protected:
long TimeNow();
bool validChkSum(ushort* buffer,int size);
u_short ChkSum(u_short* pIcmpData,int iDataLen);
int ParseRecv(IPHEAD* pHeader,int size);
public:
CICMP(int pkgSize = 0):m_iPkgSize(pkgSize){memset(m_szIcmpData,0,MAXBUFFLEN);}
int CreateRawSocket();
int Ping(const char* szIp,int pkgSize);
int Stat();
int Receive();
};
#endif
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
<
测试程序
int main(int argc,char** argv)
{
if(argc != 2)
{
cout << "argument: host" << endl;
return 0;
}
char* szIp = argv[1];
CICMP icmp;
if(icmp.CreateRawSocket() != 0)
{
cout << "create socket failed" << endl;
return 0;
}
if(icmp.Ping(szIp,4) != 0)
{
cout << "ping failed" << endl;
return 0;
}
//cout << "send success ,begin to receive" << endl;
if(icmp.Receive() != 0)
{
return 0;
}
icmp.Stat();
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
<
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包
点赞
收藏
评论
打赏
- 分享
- 举报
评论
0个
手气红包

相关专栏
-
浏览量:1819次2020-08-07 16:54:02
-
浏览量:7361次2020-07-17 15:42:06
-
浏览量:798次2023-05-16 10:55:38
-
浏览量:2242次2019-12-03 16:19:11
-
浏览量:2014次2020-09-15 09:35:02
-
浏览量:3161次2022-05-26 10:04:36
-
浏览量:1340次2023-06-12 14:36:04
-
浏览量:2428次2024-03-01 16:01:03
-
浏览量:1134次2023-04-19 09:11:57
-
浏览量:2278次2020-08-04 20:32:16
-
浏览量:2271次2020-09-09 11:24:05
-
浏览量:2058次2020-08-07 08:52:41
-
浏览量:1735次2023-10-12 14:39:21
-
2024-02-01 15:28:12
-
浏览量:1571次2020-08-07 17:15:53
-
浏览量:721次2024-01-03 09:56:52
-
浏览量:2790次2020-07-07 09:24:18
-
浏览量:2045次2020-08-13 17:45:37
-
浏览量:2591次2020-07-17 17:00:06
置顶时间设置
结束时间
删除原因
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
打赏作者
big_anana
您的支持将鼓励我继续创作!
打赏金额:
¥1

¥5

¥10

¥50

¥100

支付方式:

举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
审核成功
发布时间设置
发布时间:
请选择发布时间设置
是否关联周任务-专栏模块
审核失败
失败原因
请选择失败原因
备注
请输入备注