fasionchan

读万卷书,行万里路,品万味肴,撸万行码。

TCP设计精髓

| Comments

TCP是在不可靠的网络层之上,实现的一种面向连接的可靠的传输层协议。 为了实现可靠性并尽量优化传输效率,TCP作者们考虑到方方面面,并设计了一系列巧妙的算法。

纳格算法

纳格算法(Nagle's algoritm),主要思想是以减少发送量来增进TCP/IP网络的性能。

先来看一个场景——小数据包问题: 在远程终端操作中(telnet),客户端所输入的每一个字符源源不断发送给服务端,服务端再根据输入内容进行回传显示。 这时,有大量的小数据包产生,很多都是只有一个字节(或者若干个字节)。 众所周知,TCP数据包头部就有40字节(TCPIPv4各占20字节)。 这意味着,41字节的数据包只有1字节的有用信息,效率何等低下! 如果TCP立即发送应用产生的小数据包,那么慢速网络或者拥塞的环境下,情况将变得更糟糕。

那么,有什么办法可以解决这个问题吗?显而易见的做法是,对待发送数据进行合并之后再行提交。 这就是纳格算法的主要思想: 如果上次提交的数据还未收到对端确认,先持续缓冲数据包,直到一定大小才提交; 收到确认后,马上发送缓冲区中的数据包,不管数量是多少。

1
2
3
4
5
6
7
8
if 缓冲区非空
    if 窗口大小 >= MSS and 缓冲数据 >= MSS
        理解发送MSS大小的分组
    else
        if 还有数据待确认
            继续缓冲数据(延迟发送)
        else
            理解发送数据

捎带确认

TCP连接的两端进行通信,AB发送一段数据,B需要确认数据收到(ACK)。 B每次收到数据立即回复ACK包,代价有点大,40个字节的TCP分组就为了告诉对方,”我已经收到数据了!“。 如果B刚好有数据需要发送,那么将ACK放在数据分组里(其实ACK只是一个标志位)捎带过去岂不更好? 因此,将ACK延迟到需要发送数据时才发送出去,可以零成本完成数据确认。

如果B不发送数据,那该咋整呢?长时间不回复ACK,对端该重传数据了,那更糟! 事实上,TCP会启动一个定时器,大概是200ms。 在这段时间内,如果有新数据分组要发送,那ACK刚好借这趟便车。 否则,TCP会回复一个独立的ACK包,这也是没有办法的事情了。 当然了,定时器选定也比较考究,需要足够长以便等到数据分组便车,但又不能太长导致对端重传数据。

Comments