PING(Packet InterNet Groper)中文名为因特网包探索器,是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把回复报文传回给发送者,这有点象潜水艇声纳系统中使用的发声装置。所以,我们想知道我这台主机能不能和另一台进行通信,我们首先需要确认的是我们两台主机间的网络是不是通的,也就是我说的话能不能传到你那里,这是双方进行通信的前提。在Linux下使用指令ping的方法和现象如下:
PING的实现看起来并不复杂,我想自己写代码实现这个功能,需要些什么知识储备?我简单罗列了一下:
·ICMP协议的理解
·RAW套接字
·网络封包和解包技能
搭建这么一个ping程序的步骤如下:
1、ICMP包的封装和解封
2、创建一个线程用于ICMP包的发送
3、创建一个线程用于ICMP包的接收
4、原始套接字编程
PING的流程如下:
一、ICMP包的封装和解封
(1) ICMP协议理解要进行PING的开发,我们首先需要知道PING的实现是基于ICMP协议来开发的。要进行ICMP包的封装和解封,我们首先需要理解ICMP协议。ICMP位于网络层,允许主机或者路由器报告差错情况和提供有关异常情况的报告。ICMP报文是封装在IP数据报中,作为其中的数据部分。ICMP报文作为IP层数据报的数据,加上数据报头,组成IP数据报发送出去。ICMP报文格式如下:
ICMP报文的种类有两种,即ICMP差错报告报文和ICMP询问报文。PING程序使用的ICMP报文种类为ICMP询问报文。注意一下上面说到的ICMP报文格式中的“类型”字段,我们在组包的时候可以向该字段填写不同的值来标定该ICMP报文的类型。下面列出的是几种常用的ICMP报文类型。
我们的PING程序需要用到的ICMP的类型是回送请求(8)。
因为ICMP报文的具体格式会因为ICMP报文的类型而各不相同,我们ping包的格式是这样的:
(2) ICMP包的组装
对照上面的ping包格式,我们封装ping包的代码可以这么写:
void icmp_pack(struct icmp* icmphdr, int seq, int length){ int i = 0; icmphdr->icmp_type = ICMP_ECHO; //类型填回送请求 icmphdr->icmp_code = 0; icmphdr->icmp_cksum = 0; //注意,这里先填写0,很重要! icmphdr->icmp_seq = seq; //这里的序列号我们填1,2,3,4.... icmphdr->icmp_id = pid & 0xffff; //我们使用pid作为icmp_id,icmp_id只是2字节,而pid有4字节 for(i=0;iicmp_data[i] = i; //填充数据段,使ICMP报文大于64B } icmphdr->icmp_cksum = cal_chksum((unsigned short*)icmphdr, length); //校验和计算}
评论列表()