linuxping命令源码分析

worktile 其他 632

回复

共3条回复 我来回复
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Linux ping命令是用于测试网络连接的常用命令,它使用ICMP协议来发送数据包并等待目标主机的回复。下面对Linux ping命令的源码进行分析。

    首先,Linux ping命令的源码主要由三个文件组成:
    1. ping.c:这个文件包含了ping命令的主要逻辑。
    2. ping_common.c:这个文件包含了一些公共的函数,用于处理和发送ICMP数据包。
    3. ping.h:这个文件定义了一些常量和数据结构。

    在ping.c文件中,主要包含了以下几个函数:
    1. main函数:这个函数是程序的入口点,它解析命令行参数,初始化一些变量,并调用其他函数来执行ping的逻辑。
    2. setup函数:这个函数用于设置一些变量,比如设置ping的目标地址、ping的次数、发送数据包的大小等。
    3. ping4和ping6函数:这两个函数分别用于发送IPv4和IPv6的ICMP数据包,并接收目标主机的回复。
    4. sendping函数:这个函数用于发送ICMP数据包。
    5. print_report函数:这个函数用于打印ping的统计信息,比如发送的数据包数量、接收到的回复数量、丢失的数据包数量等。

    在ping_common.c文件中,主要包含了一些函数,用于处理和发送ICMP数据包:
    1. setup_icmp_header函数:这个函数用于设置ICMP数据包的头部信息,比如设置类型、代码、校验和等。
    2. checksum函数:这个函数用于计算ICMP数据包的校验和。
    3. send_packet函数:这个函数用于发送ICMP数据包。

    在ping.h文件中,定义了一些常量和数据结构,包括ICMP数据包的头部结构、默认的数据包大小、ICMP类型常量等。

    综上所述,Linux ping命令的源码主要包含了ping.c、ping_common.c和ping.h三个文件,其中ping.c文件包含了ping命令的主要逻辑,ping_common.c文件包含了一些公共的函数,用于处理和发送ICMP数据包,ping.h文件定义了一些常量和数据结构。这些代码共同实现了ping命令的功能,并提供了发送ICMP数据包、接收目标主机回复、打印统计信息等功能。

    2年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    1. 引入头文件及预处理部分:
    首先,Linux ping命令源码会引入一些必要的头文件,如 sys/types.h、sys/socket.h、netinet/in.h等。接着,在预处理部分会定义一些常量和宏,如定义报文的大小、设置ICMP头部的长度等。

    2. 创建原始套接字:
    接着,Linux ping命令会调用socket()函数创建一个原始套接字(raw socket)。原始套接字允许应用程序直接访问网络层协议(如ICMP),因此可以发送和接收原始IP数据包。

    3. 构造ICMP报文:
    然后,Linux ping命令会构造一个ICMP报文。这个报文包含了ICMP头部和数据部分。ICMP头部中包含了类型、代码、校验和等字段。数据部分一般是当前时间戳。

    4. 发送ICMP报文:
    接下来,Linux ping命令会调用sendto()函数发送构造好的ICMP报文。sendto()函数将报文发送到目标主机。

    5. 接收ICMP回复报文:
    最后,Linux ping命令会调用recvfrom()函数接收对应的ICMP回复报文。如果接收到回复报文,就输出相应的信息。

    总结:
    在Linux ping命令的源码中,首先会引入头文件并进行预处理,然后创建一个原始套接字,接着构造ICMP报文,发送ICMP报文,最后接收ICMP回复报文。整个过程中涉及到网络编程的基本知识,如原始套接字、ICMP报文的构造和发送等。通过分析源码,我们可以更加深入地了解ping命令的实现原理。

    2年前 0条评论
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    一、Linux ping命令概述
    在Linux系统中,ping命令是一个常用的网络诊断工具,用于检测主机之间的连通性。它通过发送ICMP回显请求消息并接收ICMP回显应答消息来测试目标主机是否可达,以及计算往返时间(RTT)以及丢包率等信息。本文将对Linux ping命令的源码进行分析。

    二、源码目录结构
    在Linux系统中,ping命令的源码包含在iputils软件包中。可以从官方网站或者通过在终端中使用以下命令进行下载:
    “`
    $ sudo apt-get install iputils-ping
    “`

    下载完成后,源码文件位于`ping`目录下,目录结构如下:
    “`
    ping
    ├── COPYRIGHT
    ├── getopt.h
    ├── iputils-ping-stamp.h
    ├── Makefile.am
    ├── ping.c
    ├── ping_common.c
    ├── ping_common.h
    └── README
    “`

    其中,源码文件`ping.c`是主要的源码文件,其他文件用于辅助实现。

    三、源码分析
    1. 引用头文件
    源码文件`ping.c`的第一步是引入头文件,包括标准库头文件、系统库头文件以及自定义头文件。例如:
    “`c
    #include
    #include
    #include
    #include
    //…
    #include “ping_common.h”
    “`
    其中,`ping_common.h`是自定义的头文件,包含了ping命令的一些公用函数、宏定义等。

    2. 定义全局变量
    接下来,源码文件定义了一些全局变量,用于存储命令行参数、网络相关信息以及计算统计数据等。例如:
    “`c
    unsigned char packet[1024];
    struct sockaddr_in dest_addr;
    int pingsock;
    unsigned long nreceived = 0;
    unsigned long ntransmitted = 0;
    “`
    其中,`packet`用于存储发送和接收的ICMP消息,`dest_addr`用于存储目标主机的网络地址,`pingsock`是socket描述符,`nreceived`和`ntransmitted`分别用于统计接收和发送的消息数量。

    3. 解析命令行参数
    源码文件使用`getopt`函数解析命令行参数,并设置相关选项。例如:
    “`c
    while ((c = getopt(argc, argv, COMMON_OPTIONS “vVaAbBc:DdfnqRr:s:w:”)) != -1) {
    switch (c) {
    case ‘h’:
    usage(stdout, 0);
    break;
    case ‘v’:
    options |= F_VERBOSE;
    break;
    //…
    default:
    usage(stderr, 1);
    }
    }
    “`
    其中,`COMMON_OPTIONS`是一个字符串,包含了一些常用的选项,例如`-h`用于显示帮助信息,`-v`用于显示详细信息等。

    4. 创建socket
    接下来,源码文件通过调用`socket`函数创建一个套接字,并设置相关选项。例如:
    “`c
    /* Open RAW socket */
    pingsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (pingsock < 0) { perror("socket"); exit(2);}```其中,`AF_INET`表示使用IPv4协议,`SOCK_RAW`表示原始套接字,`IPPROTO_ICMP`表示使用ICMP协议。5. 设置信号处理函数源码文件设置了一个信号处理函数,用于接收SIGINT信号并关闭socket。例如:```cvoid cleanup(int sig) { close(pingsock); exit(0);}if (signal(SIGINT, cleanup) == SIG_ERR) { perror("Unable to set up signal handler"); exit(2);}```当用户按下Ctrl+C时,会发送SIGINT信号,程序接收到该信号后会调用`cleanup`函数进行清理工作。6. 发送ICMP消息源码文件通过调用`sendto`函数发送ICMP消息,以及调用`recv`函数接收ICMP消息。例如:```cn = sendto(pingsock, outpacket, datalen, 0, (struct sockaddr *)&dest_addr, sizeof dest_addr);if (n < 0 || n != datalen) { if (n < 0) perror("sendto"); fprintf(stderr, "write failed (%s)\n", strerror(errno)); continue;}/* Wait for reply, with a timeout */while (1) { int cc; struct sockaddr_in from; socklen_t fromlen = sizeof(from); /* ... */ cc = recv(pingsock, packet, sizeof(packet), 0); if (cc < 0) { if (errno == EINTR) continue; perror("recv"); continue; } /* ... */}```其中,`outpacket`是构造的ICMP消息,`datalen`表示消息长度,`dest_addr`是目标主机的网络地址。7. 解析ICMP消息源码文件对接收到的ICMP消息进行解析,并根据消息类型进行相应的处理。例如:```cstruct icmphdr icmp_hdr;struct iphdr ip_hdr;/* Extract the ICMP header */memcpy(&icmp_hdr, packet + bytes, sizeof(icmp_hdr));bytes += sizeof(icmp_hdr);/* Extract the IP header */memcpy(&ip_hdr, packet + bytes, sizeof(ip_hdr));bytes += sizeof(ip_hdr);/* ... */if (icmp_hdr.type == ICMP_ECHOREPLY || icmp_hdr.type == ICMP_ECHO) { /* ... */} else if (icmp_hdr.type == ICMP_TIME_EXCEEDED) { /* ... */} else { /* ... */}```其中,`icmp_hdr`表示ICMP消息头部,`ip_hdr`表示IP消息头部。8. 输出统计信息最后,源码文件根据命令行参数和接收到的ICMP消息输出相应的统计信息。例如:```cprintf("%s icmp_seq=%u", inet_ntoa(addr.sin_addr), icmp_hdr.un.echo.sequence);printf(" bytes=%d ttl=%d", ntohs(ip_hdr.tot_len), ip_hdr.ttl);printf(" time=%s ms\n", str);nreceived++;```其中,`inet_ntoa`函数用于将网络地址转换为字符串形式,`icmp_hdr.un.echo.sequence`表示发送和接收的ICMP消息的序列号,`ip_hdr.tot_len`表示IP消息的总长度,`ip_hdr.ttl`表示IP包的生存时间。四、总结以上是对Linux ping命令源码的简单分析。源码文件`ping.c`是整个程序的主要实现部分,通过分析源码可以了解ping命令的基本原理以及实现方法。还有其他辅助文件和函数用于实现一些功能,感兴趣的读者可以进一步了解。

    2年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部