TCP的延迟ACK机制
TCP的延迟ACK机制一说到TCP,人们就喜欢开始扯三步握手之类的,那只是其中的一个环节而已。实际上每一个数据包的正确发送都是一个类似握手的过程,可以简单的把它视为两步握手。一个发送,一个反馈。但无论发送还是反馈都是有成本的,所以就有了延迟ACK机制。
TCP虽然是传输层协议的,但它毕竟是一个高级协议,它的数据传输也是基于上一层协议的数据帧的。即使一次发送一个字节的数据,也需要一个几十字节的IP包头来装配,更何况TCP的传输是两步的,是需要反馈确认的,那样的话效率就非常低。所以就像我们合并HTTP请求一样,TCP自身也有一种机制来合并一些ACK反馈消息,这就是延迟ACK机制。
当一个数据发送时,发送放一开始并不知道数据是否发送成功,它只能等对方的ACK反馈。当然,在交互过程中一次也不止处理一个数据包,不需要确认前一个包是否已发送就可以发送后面的数据,因为接收方会负责给这些包排序,不用担心顺序问题。而延迟ACK机制就是让接收方在收到数据后不立即反馈ACK消息,而是等到一小段时间,如果之后还有收到其他包就把这些ACK消息一起放入一个包中反馈给客户端。
这个延迟ACK机制并不会延迟太长时间,因为发送端对ACK反馈消息的等待是有时限的,这就是TCP对数据传输时的超时时间。如果延迟太久可能会导致超时,所以这个延迟ACK的值通常不会超过200ms。
如果我们做一个上传的程序要显示进度条,那就需要知道每个包是否都发送成功。而延迟ACK机制就会让这个成功报告延迟,发送端的统计频率就会变低。当然,很多高级语言自带的Socket封装并没有提供收到ACK反馈消息时的触发事件,所以上传进度条的实现在很多时候是非不容易的。
这个延迟ACK机制还会给计算网络延迟带来影响。因为接收端在收到数据时并不立即反馈,这个等待的时间对于发送端来说会被算入网络延迟中。这就是为什么有时候即便是局域网的TCP测试也会有很大延迟的原因。
当然,延迟ACK只是TCP的一个机制而已,它并不总被启用。TCP是很智能的,它会根据传输的“经验”来自动选择最适用的算法,延迟ACK只是其中的一个选择而已。