当前位置:看书小说 > 其他小说 > IT入门到精通及应用领域 > 第68 章 ICMP

第68 章 ICMP

<< 上一章 返回目录 下一章 >>
    icmp(inter control message protocol,互联网控制报文协议)是一种用于在ipv4网络中发送控制消息的协议。icmp消息通常用于错误报告和诊断功能,帮助网络设备(如路由器和主机)报告错误情况并诊断网络问题。

    icmp基于ip协议,但在数据报中使用不同的协议号(1)。icmp消息可以分为两类:

    1 错误报告消息:这些消息用于报告错误情况。例如:

    - 目的不可达(destination unreachable):当数据包无法到达目的地时,路由器会发送此消息,报告原因,如网络不可达、主机不可达、端口不可达等。

    - 源抑制(source quench):当路由器因为拥塞而无法处理更多数据包时,它可以发送此消息给发送方,请求发送方减缓发送速度。

    - 重定向(redirect):当路由器发现发送方可以通过其他路由器到达目的地时,它可以发送此消息,告知发送方使用更优路径。

    2 信息请求与应答消息:这些消息用于诊断网络问题。例如:

    - 回送请求(echo request):发送此消息以请求接收方回复一个回送应答(echo reply)消息。这通常用于测试网络连通性和延迟。

    - 时间戳请求(timestamp request):发送此消息以请求接收方回复一个时间戳应答(timestamp reply)消息。这通常用于测量网络延迟和路径。

    icmp协议对于网络管理和故障排查具有重要意义。然而,它也可能被滥用,如用于网络扫描和拒绝服务攻击(dos)等。因此,在某些情况下,防火墙可能会限制或过滤icmp消息。

    通过使用icmp,网络设备可以检测并报告连接问题、网络拥塞、路由选择错误等问题,从而有助于网络管理和故障排查。

    以下是icmp的主要作用:

    1 错误报告:icmp可以用于报告数据包传输过程中的错误。当数据包无法到达目的地时,路由器会发送icmp错误消息通知发送方,说明无法交付数据包的原因,如网络不可达、主机不可达、端口不可达等。这有助于诊断网络问题并优化路由选择。

    2 信息请求与应答:icmp可以用于诊断网络问题。例如,通过发送回送请求(echo request)消息,可以测试网络连通性;通过发送时间戳请求(timestamp request)消息,可以测量网络延迟和路径。

    3 拥塞控制:icmp可以用于控制网络拥塞。当路由器因为拥塞而无法处理更多数据包时,它可以发送源抑制(source quench)消息给发送方,请求发送方减缓发送速度。

    4 路径优化:icmp可以用于优化路由选择。当路由器发现发送方可以通过其他路由器到达目的地时,它可以发送重定向(redirect)消息,告知发送方使用更优路径。

    以下是一个关于icmp的简单示例。假设有两台主机a和b,它们之间通过一个路由器r进行通信。

    1 网络连通性测试:主机a想要测试与主机b之间的网络连通性。为此,它向主机b发送一个icmp回送请求(echo request)消息。

    2 主机b回应:当主机b收到icmp回送请求消息时,它会回应一个icmp回送应答(echo reply)消息。

    3 主机a收到回应:主机a收到主机b的回送应答消息后,可以确定与主机b之间的网络连接正常。主机a可以根据来回时间计算延迟,从而了解网络性能。

    这个示例展示了icmp在诊断网络问题中的作用。通过发送和接收icmp消息,主机a可以测试与主机b之间的网络连通性,以及测量网络延迟。

    以下是一个使用python的`socket`库发送和接收icmp回送请求/应答(echo request/reply)消息的示例。在这个例子中,我们将使用`socket`库的`af_i`地址族和`sock_raw`套接字类型来创建一个原始套接字,以便直接发送和接收icmp数据包。

    ```python

    import socket

    import struct

    import time

    构建icmp头部

    def create_icmp_header(id=1, seq=1):

    header = structpack(&39;bbhhh&39;, 8, 0, id, seq, 0)

    return header

    发送icmp回送请求

    def send_echo_request(sock, target_ip):

    target_addr = socketgethostbyname(target_ip)

    icmp_header = create_icmp_header()

    socksendto(icmp_header, (target_addr, 1))

    接收icmp回送应答

    def receive_echo_reply(sock):

    recv_packet = sockrecvfrom(4096)

    icmp_header, addr = recv_packet

    解析icmp头部

    type, code, checksum, id, seq = structunpack(&39;bbhhh&39;, icmp_header)

    return addr, id, seq

    主程序

    def main():

    icmp_socket = socketsocket(socketaf_i, socketsock_raw, socketgetprotobyname(&39;icmp&39;))

    target_ip = input(&34;enter the target ip address: &34;)

    send_echo_request(icmp_socket, target_ip)

    print(&34;waiting for reply&34;)

    addr, id, seq = receive_echo_reply(icmp_socket)

    print(f&34;reply received from {addr} with id: {id}, sequence: {seq}&34;)

    icmp_socketclose()

    if __name__ == &39;__main__&39;:

    main()

    ```

    这个示例首先创建了一个原始套接字,用于发送和接收icmp数据包。然后,它向目标ip地址发送一个icmp回送请求,并等待回送应答。接收到应答后,它会打印出应答数据包的源地址、id和序列号。

    需要注意的是,这个示例仅适用于具有root权限或具有cap__raw能力的用户。此外,在实际网络环境中,由于防火墙和网络地址转换(nat)等机制的影响,这个示例可能无法正常工作。在实际应用中,您可能需要使用专门的网络工具(如`ping`)或库(如`scapy`)来实现类似的功能。
<< 上一章 返回目录 下一章 >>
添加书签