网络是怎样连接的(十八)—— 将服务器的响应包从 IP 传递给 TCP

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

前言

前面的文章中我们讲述了 IP 模块生成 IP 头部和 MAC 头部。完成了 IP 模块的工作之后,下面就该轮到网卡将网络包发送出去。这部分内容涉及将 IP 包转换成电信号或光信号发送过去,这部分内容我们暂时先不研究,直接探索将服务器的响应包从 IP 传递给 TCP 的过程。

名词解释

ICMP

ICMP(Internet Control Message Protocol)Internet 控制报文协议。它是 TCP/IP 协议簇的一个自协议。用于在 IP 主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本文的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。

ICMP 使用 IP 的基本支持,就像它是一个更高级别的协议,但是 ICMP 实际上是 IP 的一个组成部分,必须由每个 IP 模块实现。

IP 模块工作步骤

下面我们来看下 IP 模块具体工作步骤。

下面我们假设 Web 服务器返回了一个网络包,那么协议栈会进行哪些处理呢?服务器返回的包的以太类型应该是 0800,因此网卡驱动程序会将其交给 TCP/IP 协议栈来进行处理。

接下来就轮到 IP 模块先工作了。

第一步是检查 IP 头部,确认格式是否正确。如果格式没有问题,下一步就是查看接收方 IP 地址。如果接收网络包的设备是一台 Windows 客户端计算机,那么服务器返回的包的接收方 IP 地址应该与客户端网卡的地址一直,检查确认之后我们就可以接收这个包了。

如果接收方 IP 地址不是自己的地址,那一定是发生了什么错误。客户端计算机不负责对包进行转发,因此不应该收到不是发给自己的包(如果是服务器就不一定了。服务器的操作系统具备和路由器相同的包转发功能,当打开这一功能时,它就可以像路由器一样对包进行转发。在这种情况下,当收到不是自己的包的时候,就会像路由器一样执行包转发操作。)。

当发生这样的错误时,IP 模块会通过 ICMP 消息将错误告知发送方。ICMP 规定了各种类型的消息。让我们遇到这个错误时,IP 模块会通过 Destination unreachable 消息通知对方。

主要的 ICMP 消息如下表所示:

消息 类型 含义
Echo reply 0 响应 Echo 消息
Destination unreachable 3 出于某些原因包没有到达目的地而是被丢弃,则通过此消息通知发送方。可能的原因包括目标 IP 地址在路由表中不存在;目标端口号不存在对应的套接字;需要分片,但分片被禁用
Source quench 4 当发送的包数量超过路由器的转发能力时,超过的部分会被丢弃,这是会通过这一消息通知发送方。但是,并不是说遇到这种情况一定会发这一消息。当路由器的性能不足时,可能连这条消息都不发送,就直接把多余的包丢弃了。当发送方收到这条消息时,必须降低发送速
Redirect 5 当查询路由表后判断该包的入口和出口为同一个网络接口时,则表示这个包不需要该路由器转发,可以由发送方直接发送给下一个路由器。遇到这种情况时,路由器会发送这条消息,给出下一个路由器的 IP 地址,指示发送方直接发送过去
Echo 8 ping 命令发送的消息。收到这条消息的设备需返回一个 Echo reply 消息,以便确认通信对象是否存在
Time exceeded 11 由于超过了 IP 头部中的 TTL 字段表示的存活时间而被路由器丢弃,此时路由器会向发送方发送这条消息
Parameter problem 12 由于 IP 头部字段存在错误而被丢弃, 此时会向发送方发送这条消息

如果接收方 IP 地址正确,则这个包会被接受下来,这是还需要完成另外一项工作。IP 协议有一个叫做分片的功能,简单来说,网线和局域网中只能传送小包,因此需要将大的包切分成多个小包。如果接收到的包是经过分片的,那么 IP 模块会将它们还原成原始的包。

分片的包会在 IP 头部的标志字段中进行标记,当收到分片的包时,IP 模块会将其暂存在内部的内存空间中,然后等待 IP 头部中具有相同 ID 的包全部到达,这是因为同一个包的所有分片都具有相同的 ID。

此外,IP 头部还有一个分片偏移量(fragment offset)字段,它表示当前分片在整个包中所处的位置。

根据这些信息,在所有分片全部收到之后,就可以将它们还原成原始的包,这个操作叫做 分片重组

到这里,IP 模块的工作就结束了,接下来包会被交给 TCP 模块。TCP 模块会根据 IP 头部中的接收方和发送方 I P地址,以及 TCP 头部中的接收方和发送方端口号来查找对应的套接字。找到对应的套接字之后,就可以根据套接字中记录的通信状态,执行相应的操作了。例如,如果包的内容是应用程序数据,则返回确认接收的包,并将数据放入缓冲区,等待应用程序来读取;如果是建立或断开连接的控制包,则返回相应的响应控制包,并告知应用程序建立和断开连接的操作状态。

参考文档

  • 《网络是怎样连接的》—— 户根勤

往期文章

猜你喜欢

转载自juejin.im/post/7087515568428810271