以 “键入 URL 到网页显示,发生了什么?” 来跑一遍整个 TCP/IP 体系

Linux 接收数据的过程

发送数据的过程类似,但是要注意发送数据的拷贝次数

发送网络数据的时候,涉及几次内存拷贝操作?

第一次,调用发送数据的系统调用的时候,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区。

第二次,在使用 TCP 传输协议的情况下,从传输层进入网络层的时候,每一个 sk_buff 都会被 克隆一个新的副本出来 。副本 sk_buff 会被送往网络层,等它发送完的时候就会释放掉,然后原始的 sk_buff 还保留在传输层,目的是为了实现 TCP 的可靠传输 ,等收到这个数据包的 ACK 时,才会释放原始的 sk_buff 。

第三次,当 IP 层发现 sk_buff 大于 MTU 时才需要进行。会再申请额外的 sk_buff,并将原来的 sk_buff 拷贝为多个小的 sk_buff。

因此,应用在发送数据的时候,应该控制单个 packet 的长度 + TCP 首部 + IP 首部 不超过 MTU,以避免第三次拷贝(TCP 有 MSS 限制,在 TCP 这一层次就会分片,而不是在网络层分片,减少重传的数据量)