ICMP是网络协议的一部分,属于网络层协议(OSI模型中的第3层)。它的作用是在IP网络中传输控制消息,以响应网络故障或传输异常。在ICMP消息的流程中,碰巧也会涉及到端口号。在本文中,我们将从多个方面深入探讨icmp端口号是多少。
一、ICMP端口号介绍
ICMP消息是基于IP协议的,其消息格式中并没有端口号这个字段。因此,我们在传输ICMP消息时,并不需要设置端口号。然而,在收到ICMP消息时,是需要通过端口号将消息传递给相应的进程的。
ICMP消息是通过IP数据包传输的,在传输时使用数据包的类型码来确定如何处理数据包。在很多情况下,ICMP消息可以看作一个特定类型的数据包。因此,在处理ICMP消息时,使用的就是与处理对应类型的IP数据包时相同的端口号。
二、ICMP端口号范围
ICMP消息所使用的端口号分为两个范围:系统保留端口和动态私有端口。
系统保留端口由IANA(Internet Assigned Numbers Authority)分配,范围是0~1023,主要用于标准化的服务和应用程序。一般而言,这些端口必须由特权进程(超级用户或管理员)打开。
动态私有端口由客户端或服务器分配,范围是49152~65535。在传输ICMP消息时,大多数情况下会使用这个范围内的端口号。
三、ICMP端口号的使用
在处理ICMP消息时,使用的端口号并不是与ICMP消息绑定的。相反,它是与进程绑定的。这就是为什么需要将收到的ICMP消息传递到相应进程的原因。
在大多数情况下,系统会使用动态分配的端口来发送ICMP消息。这个过程通常是由内核处理的,因此并不需要我们手动设置端口号。我们可以通过捕获ICMP消息,然后查看源IP地址与端口号来确认消息来源。同时,我们也可以使用ICMP的类型码和代码来判断消息的类型,然后根据消息类型来执行相应的操作。
四、代码示例
import os import socket import struct import time # 构造ICMP消息 def icmp_echo_request(): # 定义ICMP类型和代码 icmp_type = 8 # ICMP Echo Request icmp_code = 0 # must be zero # 构造ICMP消息头部 icmp_header = struct.pack('!BBHHH', icmp_type, icmp_code, 0, 0, 0) # 构造ICMP数据 icmp_data = b'hello, world!' # 计算校验和 checksum = icmp_checksum(icmp_header + icmp_data) # 重新构造ICMP头部,将计算出的校验和写入ICMP头部 icmp_header = struct.pack('!BBHHH', icmp_type, icmp_code, checksum, 0, 0) # 最终构造ICMP消息 icmp_msg = icmp_header + icmp_data return icmp_msg # 计算ICMP校验和 def icmp_checksum(data): # data需要是16位的整数倍,所以我们需要将数据进行填充 data_len = len(data) if (data_len % 2) != 0: data += b'\x00' # 计算校验和 sum = 0 for i in range(0, data_len, 2): word = (data[i]<>16) + (sum & 0xffff) sum += (sum>>16) checksum = ~sum & 0xffff return checksum # 主函数 def main(): # 构造ICMP消息 icmp_msg = icmp_echo_request() # 构造IP数据报 dest_addr = socket.gethostbyname('www.baidu.com') # 创建socket对象 icmp_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) # 设置超时时间 icmp_socket.settimeout(5) # 发送ICMP消息 icmp_socket.sendto(icmp_msg, (dest_addr, 0)) # 接收ICMP消息 try: recv_data, addr = icmp_socket.recvfrom(1024) print('recv from', addr) # 解析ICMP消息,获取信息类型码和代码 icmp_type, icmp_code = struct.unpack('BB', recv_data[20:22]) print('type:', icmp_type, 'code:', icmp_code) except socket.timeout: print('timeout') icmp_socket.close() if __name__ == '__main__': main()