解析Linux下Ping指令的源码方法 (linux下的ping源码)

Ping是一种基于ICMP协议实现的网络连通性测试工具,可以用于检测目标主机是否在线、网络延迟等。在Linux系统下,Ping指令已经成为了日常网络命令中不可或缺的一部分。本文将使用Linux系统下的Ping指令作为案例,探究Ping指令的源码实现方法。

1. 下载并编译ICMP库

Ping指令的实现方式主要是通过发送ICMP回显请求报文(Echo Request)并等待目标主机的回复报文(Echo Response)来判断目标主机是否在线,并计算出网络延迟数据。因此,我们首先需要编译一个基于ICMP协议的库文件。

在Linux系统中,我们可以选择安装liboping或libicmp库,这里我们以libicmp库为例。我们需要下载并解压缩libicmp库源码包:

“`

wget https://github.com/hamishcoleman/linux-icmp/archive/refs/tags/v0.3.tar.gz

tar -zxvf v0.3.tar.gz

“`

接着,在源代码目录下执行以下命令来编译libicmp库:

“`

cd linux-icmp-0.3

make

“`

编译完成后,我们可以在目录下看到生成了libicmp.so动态库文件。这个库文件我们在后面的Ping指令源码中会用到。

2. 系统调用

我们知道,在Linux系统中,Ping指令可以通过命令行直接运行。但是,这并不是真正的Ping指令的实现方法,而是一个运行Ping指令的程序。真正的Ping指令是通过系统调用来实现的。这里,我们以Linux 2.6为例来讲解Ping指令的实现原理。

在Linux中,系统调用是由内核提供的一组接口函数,用来实现用户空间与内核空间的交互。我们可以通过查看内核源码中的syscall.c文件来了解当前系统支持的所有系统调用。在该文件中,第0号系统调用被定义为“sys_restart_syscall”,第1号系统调用为“sys_exit”,第2号系统调用为“sys_fork”,以此类推。

Ping指令最主要的系统调用是socket()、sendto()和recvfrom()。其中,socket()用于创建一个可以发送和接收IP数据包的套接字,sendto()用于向目标主机发送ICMP回显请求报文,recvfrom()用于接收目标主机返回的ICMP回显应答报文。以下是具体的实现代码:

“`

int mn(int argc, char *argv[])

{

int sfd;

struct sockaddr_in sin;

struct icmp_packet icmp;

char buf[1024];

struct timeval start, end;

double time_diff;

if (argc != 2) {

printf(“Usage: %s IP address\n”, argv[0]);

return -1;

}

/* 创建套接字 */

sfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

if (sfd

perror(“socket”);

return -1;

}

/* 初始化目标主机地址结构体 */

memset(&sin, 0, sizeof(sin));

sin.sin_family = AF_INET;

sin.sin_addr.s_addr = inet_addr(argv[1]);

/* 初始化icmp报文 */

icmp.type = ICMP_ECHO_REQUEST;

icmp.code = 0;

icmp.checksum = 0;

icmp.id = htons(getpid());

icmp.seq = htons(1);

memset(icmp.data, 0xff, 56);

icmp.checksum = checksum((unsigned short *)&icmp, sizeof(struct icmp_packet));

/* 发送icmp报文 */

if (sendto(sfd, &icmp, sizeof(struct icmp_packet), 0, (struct sockaddr *)&sin, sizeof(sin))

perror(“sendto”);

return -1;

}

/* 接收icmp应答报文 */

if (recvfrom(sfd, buf, sizeof(buf), 0, NULL, NULL)

perror(“recvfrom”);

return -1;

}

gettimeofday(&end, NULL);

/* 计算网络延迟 */

time_diff = (end.tv_sec – start.tv_sec) + (end.tv_usec – start.tv_usec) / 1000000.0;

printf(“Time cost: %lfms\n”, time_diff * 1000);

close(sfd);

return 0;

}

“`

在以上代码中,我们可以看到使用了socket()、sendto()和recvfrom()三个系统调用来实现Ping指令的核心逻辑。其中,socket()函数创建了一个RAW套接字,这种类型的套接字可以直接发送IP数据包。sendto()函数用于向目标主机发送ICMP回显请求报文,recvfrom()函数用于从目标主机接收ICMP回显应答报文。

3. ICMP报文格式

了解Ping指令的实现原理中,必须要掌握ICMP报文格式。以下是ICMP回显请求报文和ICMP回显应答报文的具体格式。

ICMP回显请求报文格式:

“`

0 7 15 23 31

+————–+————+————+————+

| 类型 | 代码 | 校验和 | 标识符 |

+————–+————+————+————+

| 序列号 |

+————–+————+————+————+

| 数据 |

+————–+————+————+————+

“`

其中,类型为8,代码为0,标识符和序列号自定义,数据字段最多为56字节。校验和的计算方法为将16位的数据按二进制位求和,再将结果取反,得到的8位校验和填入校验和字段。

ICMP回显应答报文格式:

“`

0 7 15 23 31

+————–+————+————+————+

| 类型 | 代码 | 校验和 | 标识符 |

+————–+————+————+————+

| 序列号 |

+————–+————+————+————+

| 数据 |

+————–+————+————+————+

“`

其中,类型为0,代码为0,标识符和序列号与请求报文相同,数据字段最多为56字节。校验和的计算方法和请求报文相同。

4. 源码结构分析

在Linux系统中,Ping指令的源码主要包括三个文件:ping.c、ping.h和hostlist.c。

其中,ping.c文件是整个程序的主函数,主要实现了Ping指令的操作流程,包括创建socket、发送ICMP报文、接收ICMP报文、计算网络延迟等。在这个文件中,我们可以看到,Ping指令的实现是基于上述系统调用和ICMP报文格式的。

ping.h文件则定义了Ping指令中需要用到的各种宏定义和函数声明。

hostlist.c文件则是Ping指令的参数处理器,用于读取命令行中指定的主机列表,并将参数传递给Ping指令的主函数。

5.

通过分析Linux系统下Ping指令的源码实现方法,我们可以深入了解Ping指令的工作原理,以及基于ICMP协议的网络连通性测试实现方法。对于网络工程师来说,这些知识是非常重要的,可以帮助他们更好地理解和解决网络问题。同时,我们可以透过这个案例,学习到如何分析、理解并修改Linux系统中的源码,这对于我们的Linux系统学习和应用,也大有裨益。

相关问题拓展阅读:

linux 系统下ping -f命令

ping -f这个命令主要是搭灶加上ip是告诉用户不要分段发送,数据包就不会被路由上的网关分段。通常你所发送的数瞎散据包都会通过路由分段再发送给对方,加上此参数以后路由就不会再分磨枝氏段处理。

ping -f

尽可能快地发送报文

linux下 ping命粗仔令参数

表1 ping命令参数(linux)

参数

描述

-c count

在收发指定的count个数目的报文后停止

-d

在套接口设置so_debug

-f

尽可能快地发送报文

-i wait

设置连续报文发送时报文间的发送时间间隔(单位为秒)

-i ?device?

设置输出接口

-l preload

尽可能快地发送预载的报文,然后再返回到正常发送模式

-n

不查寻主机名,仅仅给出ip地址值

-p pattern

定义随同报文一起被发送的便笺内容(便笺最长橡凳困为16个字节)

-q

仅输出结果的总结内容

-r

不使用

路由表

来发送报文,而是直接把报文发到主机

-r

设置记录路由选择功能,即记录报文传送经过的路径

-s packetsize

设置要发送的报文大小(单位为字节,更大长度是64k,缺省长度是64)

-t tsonly

发送一个带有时间戳的ping报文

-t tsandaddr

收集梁念时间戳和地址

-t tsprespec

>>> 收集来自预定的网络段的时间戳和地址

-w timeout

指定等待每个响应的最长时间(单位是毫秒)

Flood ping. For every ECHO_REQUEST sent a period “.” is

printed, while for ever ECHO_REP received a backspace is

printed. This provides a rapid display of how many packets are

being dropped. If interval is not given, it sets interval to

zero and outputs packets as fast as they come back or one hun‐

dred times per second, whichever is more. Only the super-user

may use this option with zero interval.

我对LINUX熟,加我,我告诉你

linux下的ping源码的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux下的ping源码,解析Linux下Ping指令的源码方法,linux 系统下ping -f命令的信息别忘了在本站进行查找喔。


数据运维技术 » 解析Linux下Ping指令的源码方法 (linux下的ping源码)