ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把报文一模一样地传回给发送者,这有点象潜水艇声纳系统中使用的发声装置。 例如,在Linux终端上执行ping localhost命令将会看到以下结果: PING localhost.localdomain (127.0.0.1) from 127.0.0.1: 56(84) bytes of data. 64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=112 usec 64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=255 time=79 usec 64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=255 time=78 usec 64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=255 time=82 usec --- localhost.localdomain ping statistics --- 4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max/mdev = 0.078/0.087/0.112/0.018 ms

由上面的执行结果可以看到,ping命令执行后显示出被测试系统主机名和相应IP地址、返回给当前主机的ICMP报文顺序号、ttl生存时间和往返时间rtt(单位是毫秒,即千分之一秒)。要写一个模拟ping命令,这些信息有启示作用。要真正了解ping命令实现原理,就要了解ping命令所使用到的TCP/IP协议。ICMP(Internet Control Message,网际控制报文协议)是为网关和目标主机而提供的一种差错控制机制,使它们在遇到差错时能把错误报告给报文源发方。ICMP协议是IP层的一个协议,但是由于差错报告在发送给报文源发方时可能也要经过若干子网,因此牵涉到路由选择等问题,所以ICMP报文需通过IP协议来发送。ICMP数据报的数据发送前需要两级封装:首先添加ICMP报头形成ICMP报文,再添加IP报头形成IP数据报。由于IP层协议是一种点对点的协议,而非端对端的协议,它提供无连接的数据报服务,没有端口的概念,因此很少使用bind()和connect()函数,若有使用也只是用于设置IP地址。发送数据使用sendto()函数,接收数据使用recvfrom()函数。IP报头格式如下图:

在Linux中,IP报头格式数据结构()定义如下:

struct ip {

#if __BYTE_ORDER == __LITTLE_ENDIAN

unsigned int ip_hl:4; /* header length */

unsigned int ip_v:4; /* version */

#endif

#if __BYTE_ORDER == __BIG_ENDIAN

unsigned int ip_v:4; /* version */

unsigned int ip_hl:4; /* header length */

#endif

u_int8_t ip_tos; /* type of service */

u_short ip_len; /* total length */

u_short ip_id; /* identification */

u_short ip_off; /* fragment offset field */

#define IP_RF 0x8000 /* reserved fragment flag */

#define IP_DF 0x4000 /* dont fragment flag */

#define IP_MF 0x2000 /* more fragments flag */

#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */

u_int8_t ip_ttl; /* time to live */

u_int8_t ip_p; /* protocol */

u_short ip_sum; /* checksum */

struct in_addr ip_src, ip_dst; /* source and dest address */

};

其中ping程序只使用以下数据:IP报头长度IHL(Internet Header Length)――以4字节为一个单位来记录IP报头的长度,是上述IP数据结构的ip_hl变量。 生存时间TTL(Time To Live)――以秒为单位,指出IP数据报能在网络上停留的最长时间,其值由发送方设定,并在经过路由的每一个节点时减一,当该值为0时,数据报将被丢弃,是上述IP数据结构的ip_ttl变量。

ICMP报头格式ICMP报文分为两种,一是错误报告报文,二是查询报文。每个ICMP报头均包含类型、编码和校验和这三项内容,长度为8位,8位和16位,其余选项则随ICMP的功能不同而不同。Ping命令只使用众多ICMP报文中的两种:"请求回送'(ICMP_ECHO)和"请求回应'(ICMP_ECHOREPLY)。

在Linux中定义如下:

#define ICMP_ECHO 0

#define ICMP_ECHOREPLY 8

这两种ICMP类型报头格式如下:

在Linux中ICMP数据结构()定义如下:

struct icmp

{

u_int8_t icmp_type; /* type of message, see below */

u_int8_t icmp_code; /* type sub code */

u_int16_t icmp_cksum; /* ones complement checksum of struct */

union

{

u_char ih_pptr; /* ICMP_PARAMPROB */

struct in_addr ih_gwaddr; /* gateway address */

struct ih_idseq /* echo datagram */

{

u_int16_t icd_id;

u_int16_t icd_seq;

}ih_idseq;

u_int32_t ih_void; /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) struct ih_pmtu

{

u_int16_t ipm_void;

u_int16_t ipm_nextmtu;

} ih_pmtu;

struct ih_rtradv

{

u_int8_t irt_num_addrs;

u_int8_t irt_wpa;

u_int16_t irt_lifetime;

} ih_rtradv;

} icmp_hun;

#define icmp_pptr icmp_hun.ih_pptr

#define icmp_gwaddr icmp_hun.ih_gwaddr

#define icmp_id icmp_hun.ih_idseq.icd_id

#define icmp_seq icmp_hun.ih_idseq.icd_seq

#define icmp_void icmp_hun.ih_void

#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void

#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu

#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs

#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa

#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime

union

{

struct

{

u_int32_t its_otime;

u_int32_t its_rtime;

u_int32_t its_ttime;

}id_ts;

struct

{

struct ip idi_ip; /* options and then 64 bits of data */

} id_ip;

struct icmp_ra_addr id_radv;

u_int32_t id_mask;

u_int8_t id_data[1];

} icmp_dun;

#define icmp_otime icmp_dun.id_ts.its_otime

#define icmp_rtime icmp_dun.id_ts.its_rtime

#define icmp_ttime icmp_dun.id_ts.its_ttime

#define icmp_ip icmp_dun.id_ip.idi_ip

#define icmp_radv icmp_dun.id_radv

#define icmp_mask icmp_dun.id_mask

#define icmp_data icmp_dun.id_data

};

使用宏定义令表达更简洁,其中ICMP报头为8字节,数据报长度最大为64K字节。校验和算法――这一算法称为网际校验和算法,把被校验的数据16位进行累加,然后取反码,若数据字节长度为奇数,则数据尾部补一个字节的0以凑成偶数。此算法适用于IPv4、ICMPv4、IGMPV4、ICMPv6、UDP和TCP校验和,更详细的信息请参考RFC1071,校验和字段为上述ICMP数据结构的icmp_cksum变量。 标识符――用于唯一标识ICMP报文,为上述ICMP数据结构的icmp_id宏所指的变量。 顺序号――ping命令的icmp_seq便由这里读出,代表ICMP报文的发送顺序,为上述ICMP数据结构的icmp_seq宏所指的变量。ICMP数据报Ping命令中需要显示的信息,包括icmp_seq和ttl都已有实现的办法,但还缺rtt往返时间。为了实现这一功能,可利用ICMP数据报携带一个时间戳。使用以下函数生成时间戳:

#include int gettimeofday (struct timeval *tp, void *tzp)

其中timeval结构如下:

struct timeval

{

long tv_sec;

long tv_usec;

};

其中tv_sec为秒数,tv_usec微秒数。在发送和接收报文时由gettimeofday分别生成两个timeval结构,两者之差即为往返时间,即ICMP报文发送与接收的时间差,而timeval结构由ICMP数据报携带,tzp指针表示时区,一般都不使用,赋NULL值。 数据统计系统自带的ping命令当它接送完所有ICMP报文后,会对所有发送和所有接收的ICMP报文进行统计,从而计算ICMP报文丢失的比率。为达此目的,定义两个全局变量:接收计数器和发送计数器,用于记录ICMP报文接受和发送数目。丢失数目=发送总数-接收总数,丢失比率=丢失数目/发送总数。

在实际的Ping命令实现中,主要用到的ICMP报头的成员如下:

typedef struct _icmphdr //定义ICMP报头(回送与或回送响应)

{unsigned char i_type;//8位类型unsigned char i_code; //8位代码unsigned short i_cksum; //16位校验和unsigned short i_id; //识别号(一般用进程号作为识别号)unsigned short i_seq; //报文序列号int timestamp;//时间戳} ICMP_HEADER;

目前,IPv4的报头结构为常用的ICMP报文结构,包括ECHO-REQUEST(响应请求消息)、ECHO-REPLY(响应应答消息)、Destination Unreachable(目标不可到达消息)、Time Exceeded(超时消息)、Parameter problems(参数错误消息)、Source Quenchs(源抑制消息)、redirects(重定向消息)、Timestamps(时间戳消息)、Timestamp Replies(时间戳响应消息)、Address Masks(地址掩码请求消息)、Address Mask Replies(地址掩码响应消息)等,是Internet上十分重要的消息。

以上是我个人的一些总结,欢迎广大网友们指正!

Ping原理Linux,ping实现原理相关推荐

  1. linux ping等待时间,linux ping命令详解

    一.ping命令的原理和工作机制 ping命令一般用于检测网络通与不通,也叫时延,其值越大,速度越慢PING(PacketInternet  Grope),因特网包探索器,用于测试网络连接量的程序. ...

  2. linux 磁盘分区的原理,linux磁盘—分区原理

    回忆: IDE盘:第一块盘hda,第二块盘hdb- 第一块盘的第一个分区hda1,第二个分区hda2- SAS/SATA/SCSI盘:第一块盘sda,第二块盘sdb- 第一块盘的第一个分区sda1,第 ...

  3. linux 动态连接原理,Linux动态连接原理 GOT PLT表详解

    注意: 以下所用的连接器是指,ld, 而加载器是指ld-linux.so; 1,GOT表: GOT(Global Offset Table)表中每一项都是本运行模块要引用的一个全局变量或函数的地址.可 ...

  4. linux命令菜鸟ping,Linux ping命令

    Linux ping命令 Linux ping命令用于检测主机. 执行ping指令会使用ICMP传输协议,发出要求回应的信息,若远端主机的网络功能没有问题,就会回应该信息,因而得知该主机运作正常. 语 ...

  5. linux ping -w 命令,Linux ping 命令

    Linux ping 命令 Linux ping 命令用于检测主机. 执行 ping 指令会使用 ICMP 传输协议,发出要求回应的信息,若远端主机的网络功能没有问题,就会回应该信息,因而得知该主机运 ...

  6. ping和traceroute的工作原理

    PING原理 PING是基于ICMP协议(网络层)工作的 ICMP:Internet Control Message Protocol,互联网控制报文协议 ICMP用于报告传输过程中出现的问题,比如确 ...

  7. linux ping 虚拟网卡_虚拟机中Linux系统网卡的配置

    提示一台计算机中可能会有一个物理网卡和多个虚拟网卡,在Linux中的物理网卡的名字通常以ensXX表示 127.0.0.1被称为本地回环/环回地址,一般用来测试本机网卡是否正常 ping IP地址 然 ...

  8. Linux 路由实现原理

    目录 前言 一.什么时候需要路由 1.1 发送数据时选路 1.2 接收数据时选路 1.3 linux 路由小结 二.Linux 的路由实现 2.1 路由表 2.2 路由查找 三.路由的使用方法 3.1 ...

  9. Linux 企业级安全原理和防范技巧

    Linux 企业级安全原理和防范技巧 1. 企业级Linux系统防护概述 1.1 企业级Linux系统安全威胁 1.2 企业级Linux系统安全立体式防范体系 1.2.1 Linux文件系统访问安全 ...

最新文章

  1. leetcode--买股票的最佳时机II--python
  2. oracle 关系 表 视图_oracle动态视图v$,v_$,gv$,gv_$与x$之间的关系
  3. 在条形图中对X轴进行排序
  4. note header initialization discussion
  5. 为什么有的SAP CRM系统的产品搜索页面上会显示小红叉
  6. java时间日期工具类_java工具类--日期相关;
  7. scikit-learn学习之神经网络算法
  8. 靠谱测试人员需要具备BUG洞察能力
  9. 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛——C题 上进的凡凡
  10. C语言中用链表构建栈讲解,C语言数据结构之使用链表模拟栈的实例
  11. 数据挖掘-文本特征提取方法研究
  12. LeetCode 45 跳跃游戏||
  13. fcm算法matlab实现,fcm算法matlab
  14. “全栈”工程师 请不要随意去做
  15. 萝卜青菜各有所爱------TypeScript VS JavaScript
  16. jle汇编_汇编学习之路
  17. phpwind 安装教程图文说明
  18. 基于小程序制作一个猜拳小游戏
  19. 倒闭潮不断,众筹的生机在何处?
  20. mysql eav设计模型_Magento 2数据库EAV模型结构

热门文章

  1. centos配置启动项_查看centos开机启动项命令 - 老牛博客
  2. 计算机有没必要换硬盘,轻松更换电脑硬盘无需重装系统的方法介绍
  3. 如何迅速秒杀掉海量数据处理面试题
  4. IntelliJ IDEA:安装/搭建/配置/插件
  5. 2020-09-27程序设计基础知识
  6. java:上传微信临时文件的素材
  7. 李建忠设计模式之“对象创建”模式
  8. ZDNS受邀出席腾讯云基础资源年会,分享《2020域名行业发展报告》
  9. 极点突然中文标点变全角了
  10. 这个是可以将得到速查编码的存储过程 如 中国人 可以得到 ZGR