2.5.2 数据分用

数据帧到达目的主机时,数据沿着协议栈自底向上传递,每一层都会对数据做一些检查,如差错校验、身份识别等,确认无误后,就去掉本层协议首部。传输层以下的各层协议根据首部中协议字段中的值把数据传递给对应的上层协议处理。传输层,会根据首部中的端口号查找与它匹配的应用程序,找到了就把数据交给应用程序去处理,这个过程被称为分用。

图2.6说明了TCP/IP协议栈数据的分用过程。实际的过程要比描述的复杂。IP层收到数据后,如果数据是分片的,并不会立即把数据传给上层协议,而是保存在IP队列中,等所有的片都到达后,执行重组,再交给其他协议处理。

图2.6 以太网数据帧的分用

UDP收到数据报,执行简单的验证后就交给应用程序了;而TCP会检查收到的TCP段是否前面有数据丢失,如果有它也会先保留收到的段,等对方把丢失的段全部发送过来后,再一起交给应用程序。

TCP和UDP可以根据端口号知道把数据交给哪个程序处理,从图中还看到应用程序可以直接访问IP或ICMP,在IP或ICMP首部中并没有端口号标识应用程序,那么它们怎么知道把数据交给哪个程序处理呢?访问IP或ICMP的程序,在创建原始socket时,只会指定使用的协议,因此对于原始socket,数据是根据协议分用的,TCP/IP收到数据后会把它交给所有与协议匹配的应用程序。这样带来的问题是:两个应用程序在创建socket时,指定了相同的协议,属于一个程序的数据同时也会被另一个程序收到,协议栈中也是这样实现的,这样两个程序就会互相干扰。为了判断收到的数据是否是属于自己的,应用程序需要在发送的数据中规定自己的标识。如常用的Ping程序使用ICMP,就会在ICMP首部的ID中设置自己的标识符,通常是进程ID。这样当收到数据时,如果ID与设置的值相等,就知道这是自己的数据了。

数据在传输过程中,如红军过草地、爬雪山一样,还要经过层层检查,漫漫长征之后终于到达了目的地,真是一次艰辛的旅程,可是这又有什么关系?你只不过轻轻点了一下鼠标而已。