一文读懂:原始套接字的前世今生 原始套接字该套接字允许对较低层协议如 IP 或 ICMP进行直接访问常用于网络协议分析检验新的网络协议实现也可用于测试新配置或安装的网络设备。这类套接字可用来接受 ICMP 报文并解析出相应字段。ICMP 是 Internet Control Message Protocol(Internet控制消息协议) 的缩写。ICMP 协议是一种面向无连接的协议用于传输出错报告控制信息。它是 TCP/IP 协议族的一个子协议用于在 IP 主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据但是对于用户数据的传递起着重要的作用。当程序出现了错误它就可以向你提供一份错误报告让你得知错误的原因。就好比是公司里的某位员工哪天有事不去上班他就要向领导请假写好“请假条”告知自己的请假原因如果无故旷工领导肯定是会找麻烦的。ICMP 报文内容是放在 IP 数据包的数据部分里来互相交流的。也就是从 ICMP 的报文格式来说ICMP 是 IP 的上层协议。一个 ICMP 报文包括 IP 报头至少 20 字节、ICMP 报头至少 8 字节和 ICMP 报文属于 ICMP 报文的数据部分。当 IP 报头中的协议类型字段值为 1 时就说明这是一个 ICMP 报文。ICMP 报头如下图解析 ICMP 报文可以使用 Python 中 struct 模块的 upack() 函数来实现。其参数fmtstr: 格式化字符串packet: 需要解析的字符数组该函数的返回值可以是多个根据格式串中指定的类型返回到相应变量中。例如a,b,c,dstruct.unpack(5s6sif,bytes)则从 bytes 这个数组中解析出a5 个字符的字符串5sb6 个字符的字符串(6s)c整型(i)d浮点型数据(f)。对于 Ping 命令的 ICMP 报文我们需从 IP 包中取出 ICMP 报头位于 20 到 28 字节从中可以取出报文类型 type,代码 code校验和 checksum报文 ID 及报文序号字段对于类型为 1 的报文且其 ID 为需要接收的报文从 28 字节后面开始解析发送的数据为发送时间数据类型及长度根据发送的数据来确定。