【Shell 命令集合 网络通讯 】Linux 追踪数据包在网络中的路径 traceroute命令 使用指南

这篇具有很好参考价值的文章主要介绍了【Shell 命令集合 网络通讯 】Linux 追踪数据包在网络中的路径 traceroute命令 使用指南。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


Shell 命令专栏:Linux Shell 命令全解析


描述


traceroute命令用于追踪数据包在网络中的路径。它通过发送一系列的ICMP(Internet Control Message Protocol)回显请求数据包(ping包),并记录每个数据包的传输时间,从而确定数据包从源主机到目标主机经过的所有中间路由器。

当我们使用traceroute命令时,它会发送一系列的数据包,每个数据包的TTL(生存时间)值逐渐递增。当数据包到达某个中间路由器时,如果TTL值为0,路由器会将该数据包丢弃,并发送一个ICMP回显超时消息给源主机。通过这种方式,traceroute命令可以获取数据包经过的每个中间路由器的IP地址和传输时间。

通过分析traceroute命令的输出,我们可以确定数据包在网络中的路径,以及每个中间路由器的响应时间。这对于网络故障排除和网络性能优化非常有帮助。我们可以根据traceroute的结果,确定数据包在网络中的瓶颈位置,并采取相应的措施来改善网络性能。

总结起来,traceroute命令的作用是通过发送一系列的ICMP回显请求数据包,追踪数据包在网络中的路径,并记录每个数据包的传输时间,以便分析网络性能和故障排除。


语法格式

traceroute [选项] 目标主机

参数说明

  • -n:以数字形式显示中间路由器的IP地址,而不进行反向DNS查找。
  • -q <次数>:设置每个TTL值发送的数据包数量。
  • -I:使用ICMP Echo请求数据包(ping包)进行追踪,而不是默认的UDP数据包。
  • -w <超时时间>:设置等待每个中间路由器响应的超时时间。
  • -m <最大跳数>:设置追踪路径的最大长度,即最大跳数。
  • -f <起始TTL值>:设置起始TTL值,即从指定跳数开始追踪路径。

错误情况

  • 如果目标主机无法到达或不存在,traceroute命令将显示相关错误信息,如"无法解析主机"或"网络不可达"。
  • 如果网络中存在防火墙或路由器配置问题,可能会导致traceroute命令失败或无法显示完整的路径。
  • 如果traceroute命令的超时时间设置过短,可能会导致中间路由器无法及时响应,从而显示超时错误。

请注意,以上是一些常见的错误情况,实际情况可能因网络配置和环境而有所不同。在使用traceroute命令时,需要根据具体情况进行参数设置和错误排查。

注意事项

在使用Linux Shell中的traceroute命令时,有一些注意事项需要考虑:

  1. 需要使用管理员权限:traceroute命令需要发送和接收ICMP或UDP数据包,这通常需要管理员权限。因此,在使用traceroute命令之前,请确保您具有足够的权限,或者使用sudo来执行命令。

  2. 防火墙和路由器配置:在某些情况下,网络中的防火墙或路由器配置可能会阻止或限制traceroute命令的正常执行。如果您发现无法获取完整的路径或出现超时错误,请检查网络设备的配置,并确保允许ICMP或UDP数据包通过。

  3. 解析主机名的延迟:traceroute命令默认会尝试解析每个中间路由器的IP地址对应的主机名。这可能会导致一些延迟,特别是在网络中存在DNS问题或主机名解析较慢的情况下。如果您对延迟比较敏感,可以使用-n选项来禁用主机名解析。

  4. 超时时间的设置:traceroute命令会等待每个中间路由器的响应,如果超过了设定的超时时间仍未收到响应,将显示超时错误。默认的超时时间可能不适用于所有网络环境。您可以使用-w选项来设置合适的超时时间,以确保能够获取到足够的响应。

  5. 最大跳数的设置:traceroute命令默认的最大跳数为30,这意味着如果数据包在30个跳内未到达目标主机,将停止追踪并显示相关信息。在某些网络中,可能需要设置更大的最大跳数,以便追踪更长的路径。您可以使用-m选项来设置最大跳数。

  6. 安全性考虑:由于traceroute命令涉及发送和接收网络数据包,可能会引起一些安全问题。在某些情况下,网络管理员可能会限制或禁止使用traceroute命令。在使用traceroute命令时,请确保您已获得适当的授权,并遵守相关的安全政策和规定。

总之,在使用traceroute命令时,请确保您具备足够的权限、了解网络环境和配置,并注意安全性和延迟等因素。


底层实现

在Linux Shell中,traceroute命令的底层实现是通过发送特定类型的网络数据包来追踪路径。具体来说,它使用了ICMP(Internet Control Message Protocol)或UDP(User Datagram Protocol)数据包来实现。

当我们执行traceroute命令时,它会创建一个原始套接字(raw socket)来发送数据包。在每个数据包中,它会设置一个特定的TTL(Time to Live)值,该值指定了数据包在网络中可以经过的最大跳数。初始TTL值通常为1。

traceroute命令通过发送数据包到目标主机,并等待每个中间路由器的响应。如果一个中间路由器收到了数据包,但发现TTL值已经为0,它会丢弃该数据包,并发送一个ICMP超时消息(如果使用ICMP协议)或UDP端口不可达消息(如果使用UDP协议)给源主机。这样,traceroute命令就能够确定数据包经过的每个中间路由器的IP地址和传输时间。

为了获取更多的信息,traceroute命令会逐渐增加TTL值,并发送多个数据包,以便覆盖整个路径。它会记录每个数据包的传输时间和路由器的IP地址,然后将结果输出给用户。

需要注意的是,底层实现可能因操作系统和网络设备的不同而有所差异。不同的操作系统可能使用不同的方式来发送和接收数据包,而网络设备的配置和策略也可能会影响traceroute命令的执行和结果。

总结起来,traceroute命令底层通过发送特定类型的网络数据包(ICMP或UDP)来追踪路径。它使用TTL值来控制数据包在网络中经过的跳数,并通过接收中间路由器的响应来确定路径和传输时间。


示例

示例一

$ traceroute www.google.com

该命令将追踪到达www.google.com的路径,并显示每个中间路由器的IP地址和传输时间。

示例二

$ traceroute -n 192.168.0.1

该命令将以数字形式显示中间路由器的IP地址,而不进行反向DNS查找。

示例三

$ traceroute -q 10 www.example.com

该命令将发送10个数据包来追踪到达www.example.com的路径。

示例四

$ traceroute -I 8.8.8.8

该命令将使用ICMP Echo请求数据包(ping包)进行追踪,而不是默认的UDP数据包。

示例五

$ traceroute -w 2 www.yahoo.com

该命令将设置等待每个中间路由器响应的超时时间为2秒。

示例六

$ traceroute -m 20 www.microsoft.com

该命令将设置最大跳数为20,即追踪路径的最大长度为20跳。

示例七

$ traceroute -f 5 www.amazon.com

该命令将设置起始TTL值为5,即从第5跳开始追踪路径。


用c语言实现


下面是一个使用C语言实现traceroute命令的简单示例代码,代码中使用了原始套接字(raw socket)来发送和接收网络数据包。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netdb.h>

#define MAX_HOPS 30
#define PACKET_SIZE 64
#define ICMP_ECHO_REQUEST 8
#define ICMP_ECHO_REPLY 0
#define ICMP_TIME_EXCEEDED 11

// 计算校验和
unsigned short calculateChecksum(unsigned short *buffer, int length) {
    unsigned long sum = 0;
    while (length > 1) {
        sum += *buffer++;
        length -= 2;
    }
    if (length == 1) {
        sum += *(unsigned char *)buffer;
    }
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    return ~sum;
}

// 发送ICMP回显请求数据包
void sendEchoRequest(int sockfd, struct sockaddr_in *dest_addr, int ttl) {
    struct icmphdr icmp_header;
    memset(&icmp_header, 0, sizeof(struct icmphdr));
    icmp_header.type = ICMP_ECHO_REQUEST;
    icmp_header.code = 0;
    icmp_header.un.echo.id = getpid();
    icmp_header.un.echo.sequence = ttl;
    icmp_header.checksum = calculateChecksum((unsigned short *)&icmp_header, sizeof(struct icmphdr));

    setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(int));
    sendto(sockfd, &icmp_header, sizeof(struct icmphdr), 0, (struct sockaddr *)dest_addr, sizeof(struct sockaddr_in));
}

// 接收ICMP回显回复数据包
int receiveEchoReply(int sockfd, int ttl, struct sockaddr_in *recv_addr, float *rtt) {
    char buffer[PACKET_SIZE];
    struct timeval start_time, end_time;
    socklen_t addr_len = sizeof(struct sockaddr_in);

    gettimeofday(&start_time, NULL);
    ssize_t bytes_received = recvfrom(sockfd, buffer, PACKET_SIZE, 0, (struct sockaddr *)recv_addr, &addr_len);
    gettimeofday(&end_time, NULL);

    *rtt = (end_time.tv_sec - start_time.tv_sec) * 1000.0 + (end_time.tv_usec - start_time.tv_usec) / 1000.0;

    if (bytes_received >= sizeof(struct iphdr) + sizeof(struct icmphdr)) {
        struct iphdr *ip_header = (struct iphdr *)buffer;
        struct icmphdr *icmp_header = (struct icmphdr *)(buffer + (ip_header->ihl * 4));
        if (icmp_header->type == ICMP_ECHO_REPLY) {
            return 1; // 收到回复
        } else if (icmp_header->type == ICMP_TIME_EXCEEDED) {
            return 2; // TTL超时
        }
    }
    return 0; // 其他情况
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Usage: %s <destination>\n", argv[0]);
        return 1;
    }

    struct hostent *host = gethostbyname(argv[1]);
    if (host == NULL) {
        printf("Cannot resolve hostname.\n");
        return 1;
    }

    int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (sockfd < 0) {
        perror("Socket creation failed");
        return 1;
    }

    struct sockaddr_in dest_addr;
    memset(&dest_addr, 0, sizeof(struct sockaddr_in));
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_addr = *((struct in_addr *)host->h_addr);

    printf("Traceroute to %s (%s)\n", argv[1], inet_ntoa(dest_addr.sin_addr));

    for (int ttl = 1; ttl <= MAX_HOPS; ttl++) {
        printf("%2d ", ttl);

        for (int i = 0; i < 3; i++) {
            sendEchoRequest(sockfd, &dest_addr, ttl);

            struct sockaddr_in recv_addr;
            memset(&recv_addr, 0, sizeof(struct sockaddr_in));
            float rtt = 0.0;

            int result = receiveEchoReply(sockfd, ttl, &recv_addr, &rtt);
            if (result == 1) {
                printf(" %.3f ms", rtt);
                break;
            } else if (result == 2) {
                printf(" *");
            } else {
                printf(" ???");
            }
        }

        printf("\n");
    }

    close(sockfd);
    return 0;
}

这段代码使用了原始套接字(raw socket)来发送和接收ICMP数据包。它通过设置TTL值和发送ICMP回显请求数据包来追踪路径,并通过接收ICMP回显回复数据包来获取每个中间路由器的响应时间。代码中还包含了一些辅助函数,如计算校验和和处理时间等。

请注意,使用原始套接字需要具有管理员权限。因此,在运行该代码时,您可能需要使用sudo或以root用户身份执行。此外,由于使用了原始套接字,该代码只能在Linux等支持原始套接字的操作系统上运行。

这只是一个简单的示例,实际上,traceroute命令的实现要更加复杂,涉及到更多的选项和错误处理。此外,由于网络环境的不同,代码可能需要进行适当的调整和修改。


结语

在我们的探索过程中,我们已经深入了解了Shell命令的强大功能和广泛应用。然而,学习这些技术只是开始。真正的力量来自于你如何将它们融入到你的日常工作中,以提高效率和生产力。

心理学告诉我们,学习是一个持续且积极参与的过程。所以,我鼓励你不仅要阅读和理解这些命令,还要动手实践它们。尝试创建自己的命令,逐步掌握Shell编程,使其成为你日常工作的一部分。

同时,请记住分享是学习过程中非常重要的一环。如果你发现本博客对你有帮助,请不吝点赞并留下评论。分享你自己在使用Shell命令时遇到的问题或者有趣的经验,可以帮助更多人从中学习。
此外,我也欢迎你收藏本博客,并随时回来查阅。因为复习和反复实践也是巩固知识、提高技能的关键。

最后,请记住:每个人都可以通过持续学习和实践成为Shell编程专家。我期待看到你在这个旅途中取得更大进步!


阅读我的CSDN主页,解锁更多精彩内容:泡沫的CSDN主页

linux traceroute命令详解,# Shell命令集合,网络,linux,智能路由器,开发语言,嵌入式,c++,运维文章来源地址https://www.toymoban.com/news/detail-757049.html

到了这里,关于【Shell 命令集合 网络通讯 】Linux 追踪数据包在网络中的路径 traceroute命令 使用指南的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 物联网网络通讯知识

    RTU英文全称Remote Terminal Units,中文全称为远程终端单元。远程终端设备(RTU)是安装在远程现场的 电子设备 ,用来监视和测量安装在远程现场的传感器和设备。通俗理解就是能够编程的还可以将数据传输到服务器的工具。RTU内部是包含 通讯模块 的,RTU仪表配置服务器后,就可

    2024年02月05日
    浏览(43)
  • 网络通讯组件性能优化之路

    BIO为同步阻塞IO,blocking queue的简写,也就是说多线程情况下只有一个线程操作内核的queue,当前线程操作完queue后,才能给下一个线程操作; 问题 在BIO下,一个连接就对应一个线程,如果连接特别多的情况下,就会有特别多的线程,很费线程;在早期的时候,世界上的计算机

    2024年02月02日
    浏览(34)
  • C++ 简单实现RPC网络通讯

            RPC是远程调用系统简称,它允许程序调用运行在另一台计算机上的过程,就像调用本地的过程一样。RPC 实现了网络编程的“过程调用”模型,让程序员可以像调用本地函数一样调用远程函数。最近在做的也是远程调用过程,所以通过重新梳理RPC来整理总结一下。  

    2023年04月08日
    浏览(30)
  • 网络通讯录服务器

    简易版本 服务端完整版本 客户端完整版本 Protobuf还常⽤于通讯协议、服务端数据交换场景。那么在这个⽰例中,我们将实现⼀个⽹络版本的 通讯录,模拟实现客⼾端与服务端的交互,通过Protobuf来实现各端之间的协议序列化。 需求如下: 客⼾端可以选择对通讯录进⾏以下操

    2024年02月12日
    浏览(34)
  • http和https的区别?(网络通讯)

    HTTP:               HTTP(超文本传输协议)和HTTPS(安全超文本传输协议)都是用于互联网通信的协议,但HTTPS是一种更加安全的协议。 HTTPS:              HTTP是一种明文传输协议,信息传输的过程中没有加密,容易被黑客窃取信息。而HTTPS则在HTTP的基础上增加

    2024年02月14日
    浏览(30)
  • 关于ROS的网络通讯方式TCP/UDP

    ROS 系列学习教程(总目录) TCP/IP协议族为传输层指明了两个协议:TCP和UDP,它们都是作为应同程序和网络操作的中介物。 TCP(Transmission Control Protocol)协议全称是传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC793定义。 TCP是面向连接的、

    2024年02月05日
    浏览(29)
  • 【网络】UDP通讯(服务器/客户端)

    前言:UDP通讯实现比较简单,单某些情况下也会使用,建议先看一下说明,然后运行代码感受一下。         传输层主要应用的协议模型有两种,一种是TCP协议,另外一种则是UDP协议。TCP协议在网络通信中占主导地位,绝大多数的网络通信借助TCP协议完成数据传输。但U

    2024年02月12日
    浏览(46)
  • 内网安全——代理技术Socks5&网络通讯&控制上线

    目录 (一)前置知识 0x01 单机——防火墙之限制出入站 常见主机配置不出网的方式

    2023年04月23日
    浏览(29)
  • 【Flink网络通讯(一)】Flink RPC框架的整体设计

    我们从整体的角度看一下Flink RPC通信框架的设计与实现,了解其底层Akka通信框架的基础概念及二者之间的关系。   Akka是使用Scala语言编写的库,用于在JVM上简化编写具有可容错、高可伸缩性的Java或Scala的Actor模型。Akka基于Actor模型,提供了一个用于构建可扩展、弹性、快速响

    2024年02月21日
    浏览(32)
  • Java与Modbus-TCP/IP网络通讯

    通过Java与Modbus-TCP/IP网络通讯实现举例5中的功能

    2024年02月10日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包