频道栏目
首页 > 资讯 > 疑难 > 正文

TCP协议疑难问题集锦4

13-08-10        来源:[db:作者]  
收藏   我要投稿
TCP协议疑难问题集锦4
 
疑难杂症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 (没有超过拥塞窗口大小的数据分段未确认 || 数据分段中包含FIN ) &&
    数据分段没有超越窗口边界
    Then 
    IF 分段在中间(上述例子中的分段1和2) ||
           分段是紧急模式            ||
       通过上述的Nagle算法(改进后的Nagle算法)
        Then 发送分段
    EndIF 
EndIF
     曾经我也改过Nagle算法,确切的说不是修改Nagle算法,而是修改了“到底何时能发送数据”的策略,以往都是发送端判断能否发送数据的,可是如果此时有延迟ACK在等待被捎带,而待发送的数据又由于积累不够或者其它原因不能发送,因此两边都在等,这其实在某些情况下不是很好。我所做的改进中对待何时能发送数据又增加了一种情况,这就是“ACK拉”的情况,一旦有延迟ACK等待发送,判断一下有没有数据也在等待发送,如果有的话,看看数据是否大到了一定程度,在此,我选择的是MSS的一半:
IF (没有超过拥塞窗口大小的数据分段未确认 || 数据分段中包含FIN ) &&
     数据分段没有超越窗口边界                      
    Then 
    IF 分段在中间(上述例子中的分段1和2) ||
           分段是紧急模式            ||
       通过上述的Nagle算法(改进后的Nagle算法)
        Then 发送分段
    EndIF 
ELSE IF 有延迟ACK等待传输                &&
    发送队列中有待发送的TCP分段       &&
    发送队列的头分段大小大于MSS的一半
        Then 发送队列头分段且捎带延迟ACK 
EndIF
另外,发送队列头分段的大小是可以在统计意义上动态计算的,也不一定非要是MSS大小的一半。我们发现,这种算法对于交互式网路应用是自适应的,你打字越快,特定时间内积累的分段就越长,对端回复的越快(可以捎带ACK),本端发送的也就越快(以Echo举例会更好理解)。  
疑难杂症14:《TCP/IP详解(卷一)》中Nagle算法的例子解读
这个问题在网上搜了很多的答案,有的说RFC的建议,有的说别的。可是实际上这就是一个典型的“竞态问题”:
首先服务器发了两个分段:
数据段12:ack 14
数据段13:ack 14,54:56
然后客户端发了两个分段:
数据段14:ack 54,14:17
数据段15:ack 56,17:18
可以看到数据段14本来应该确认56的,但是确认的却是54。也就是说,数据段已经移出队列将要发送但还未发送的时候,数据段13才到来,软中断处理程序抢占了数据段14的发送进程,要知道此时只是把数据段14移出了队列,还没有更新任何的状态信息,比如“发出但未被确认的分段数量”,此时软中断处理程序顺利接收了分段13,然后更新窗口信息,并且检查看有没有数据要发送,由于分段14已经移出队列,下一个接受发送检查的就是分段15了,由于状态信息还没有更新,因此分段15顺利通过发送检测,发送完成。
     可以看Linux的源代码了解相关信息,tcp_write_xmit这个函数在两个地方会被调用,一个是TCP的发送进程中,另一个就是软中断的接收处理中,两者在调用中的竞态就会引起《详解》中的那种情况。注意,这种不加锁的发送方式是合理的,也是最高效的,因此TCP的处理语义会做出判断,丢弃一切不该接收或者重复接收的分段的。
~~~~~~~~~~~~~~~~~~~~
承上启下
又到了该承上启下,到此为止,我们叙述的TCP还都是简单的TCP,就算是简单的TCP,也存在上述的诸多问题,就更别提继续增加TCP的复杂性了。到此为止,我们的TCP都是端到端意义上的,然而实际上TCP要跑在IP网络之上的,而IP网络的问题是很多的,是一个很拥堵网络。不幸的是,TCP的有些关于确认和可靠性的机制还会加重IP网络的拥堵。
~~~~~~~~~~~~~~~~~~~~
 
5.IP网络之上的TCP
5.1.端到端的TCP协议和IP协议之间的矛盾
端到端的TCP只能看到两个节点,那就是自己和对方,它们是看不到任何中间的路径的。可是IP网络却是一跳一跳的,它们的矛盾之处在于TCP的端到端流量控制必然会导致网络拥堵。因为每条TCP连接的一端只知道它对端还有多少空间用于接收数据,它们并不管到达对端的路径上是否还有这么大的容量,事实上所有连接的这些空间加在一起将瞬间超过IP网络的容量,因此TCP也不可能按照滑动窗口流量控制机制很理想的运行。
     势必需要一种拥塞控制机制,反应路径的拥塞情况。
 
相关TAG标签
上一篇:android关机充电
下一篇:java 加减乘除错误
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站