ping 没有端口号, 如何保证数据的正确接收?
ping 使用 ICMP 协议, ICMP 工作在 IP层所以无端口号, 当多个进程使用ICMP 的时候, 怎么判断该 ICMP Message 属于哪个进程?
不像其他应用层的协议如http, 直接监控80端口, ping 若直接使用 ICMP, 那它怎么知道来的数据包就是属于它的呢?
负责接收处理Ping报文(ICMP Echo
Request)的进程是唯一(Unique)的,且是一个系统进程,所以压根不会有那么多的烦恼。
这个系统进程,位于TCP/IP协议栈的IP栈,所以一旦IP栈发现这是发给自己的(目的IP == self,且protocol number == 1),直接就把这个Ping报文扔给这唯一的进程处理。
可能与读者想象的不一样,Ping 1.1.1.1报文的接收方,处理起来特别简单,只要把收到的Ping报文几乎原始模样反弹(Echo Reply)回去即可。
几乎的意思是,主机=1.1.1.1 需要做几个简单操作:
- ICMP type =0 修改为8
- 重新计算ICMP checksum
- 将原始报文的Source IP(你的IP)、Destination IP (1.1.1.1)对调
- TTL重置为本地设置
- 重新计算IP checksum
做完以上操作,即可委托IP路由将Ping
Echo Reply报文发出。毕竟echo的原始意义就是反弹、回音的意思,简单哇?
同学们可能注意到ICMP报文头的“Identifier”、“Sequence Number”,接收方压根没有触碰。既然接收方根本不处理,为何还要画蛇添足呢?
因为 “Identifier” + “Sequence Number” 这个黄金搭档,不是给接收方用的,而是给发送方(题主)用的。准确地说,是当Ping报文的返回报文(Echo Request),题主主机的操作系统将根据“Identifier”定位是哪个用户进程的报文,然后把这个报文deliver给对应进程。该进程再根据“Sequence Number”匹配本地发出的Echo Request的“Sequence Number”。如果匹配成功,将该“Sequence Number”对应的定时器熄灭,计算往返时间Round Trip Time,并时间统计打印到屏幕上。
如果在定时器响之前,没有匹配的echo reply,Ping的统计为失败, timeout默认 = 2秒。
定时器响了之后,如果收到了对应的“Sequence Number” 的echo reply,直接丢弃处理,因为已经没有任何意义了。
通常“Identifier”为用户进程号,这样处理起来直观便利。如果不是直接映射,题主的主机有方法根据Identifier的值,找到对应的用户进程前来处理。总之一句话,不能造成混淆或者无法找到合适的进程处理的现象,这就是协议存在的意义!
