疑难杂症11:糊涂窗口解决方案和Nagle算法 糊涂窗口综合症患者希望发送端积累TCP分段,而Nagle算法确实保证了一定的TCP分段在发送端的积累,另外在延迟ACK的延迟的那一会时间,发送端会利用这段时间积累数据。然而这却是三个不同的问题。Nagle算法可以缓解糊涂窗口综合症,却不是治本的良药。 疑难杂症12:Nagle算法和延迟ACK 延迟ACK会延长ACK到达发送端的时间,由于标准Nagle算法只允许一个未被确认的TCP分段,那无疑在接收端,这个延迟的ACK是毫无希望等待后续数据到来最终进行积累确认的,如果没有数据可以捎带这个ACK,那么这个ACK只有在延迟确认定时器超时的时候才会发出,这样在等待这个ACK的过程中,发送端又积累了一些数据,因此延迟ACK实际上是在增加延迟的代价下加强了Nagle算法。在延迟ACK加Nagle算法的情况下,接收端只有不断有数据要发回,才能同时既保证了发送端的分段积累,又保证了延迟不增加,同时还没有或者很少有空载的ACK。要知道,延迟ACK和Nagle是两个问题的解决方案。 疑难杂症13:到底何时可以发送数据 到底何时才能发送数据呢?如果单从Nagle算法上看,很简单,然而事实证明,情况还要更复杂些。如果发送端已经排列了3个TCP分段,分段1,分段2,分段3依次被排入,三个分段都是小分段(不符合Nagle算法中立即发送的标准),此时已经有一个分段被发出了,且其确认还没有到来,请问此时能发送分段1和2吗?如果按照Nagle算法,是不能发送的,但实际上它们是可以发送的,因为这两个分段已经没有任何机会再积累新的数据了,新的数据肯定都积累在分段3上了。问题在于,分段还没有积累到一定大小时,怎么还可以产生新的分段?这是可能的,但这是另一个问题,在此不谈。 Linux的TCP实现在这个问题上表现的更加灵活,它是这么判断能否发送的(在开启了Nagle的情况下): IF 数据的大小和窗口的大小都超过了MSS Then 发送数据分段 ELSE IF 还有发出的TCP分段的确认没有到来 Then 积累数据到发送队列的末尾的TCP分段 ELSE 发送数据分段 EndIF EndIF
IF (没有超过拥塞窗口大小的数据分段未确认 || 数据分段中包含FIN ) && 数据分段没有超越窗口边界 Then IF 分段在中间(上述例子中的分段1和2) || 分段是紧急模式 || 通过上述的Nagle算法(改进后的Nagle算法) Then 发送分段 EndIF ELSE IF 有延迟ACK等待传输 && 发送队列中有待发送的TCP分段 && 发送队列的头分段大小大于MSS的一半 Then 发送队列头分段且捎带延迟ACK EndIF