TCP协议要点和难点全解

www.net130.com     日期:2014-10-15    浏览次数:
出处:codeceo 码农网

曾经我也改过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的处理语义会做出判断,丢弃一切不该接收或者重复接收的分段的。

5.IP网络之上的TCP

5.1.端到端的TCP协议和IP协议之间的矛盾

端到端的TCP只能看到两个节点,那就是自己和对方,它们是看不到任何中间的路径的。可是IP网络却是一跳一跳的,它们的矛盾之处在于TCP的端到端流量控制必然会导致网络拥堵。因为每条TCP连接的一端只知道它对端还有多少空间用于接收数据,它们并不管到达对端的路径上是否还有这么大的容量,事实上所有连接的这些空间加在一起将瞬间超过IP网络的容量,因此TCP也不可能按照滑动窗口流量控制机制很理想的运行。

势必需要一种拥塞控制机制,反应路径的拥塞情况。

● 疑难杂症15:拥塞控制的本质

由于TCP是端到端协议,因此两端之间的控制范畴属于流量控制,IP网络的拥塞会导致TCP分段的丢失,由于TCP看不到中间的路由器,因此这种丢失只会发生中间路由器,当然两个端点的网卡或者IP层丢掉数据分段也是TCP看不到的。因此拥塞控制必然作用于IP链路。事实上我们可以得知,只有在以下情况下拥塞控制才会起作用:

a.两个或两个以上的连接(其中一个一定要是TCP,另一个可以是任意连接)经过同一个路由器或者同一个链路时;

b.只有一个TCP连接,然而它经过了一个路由器时。

其它情况下是不会拥塞的。因为一个TCP总是希望独享整条网络通路,而这对于多个连接而言是不可能的,必须保证TCP的公平性,这样这种拥塞控制机制才合理。本质上,拥塞的原因就是大家都想独享全部带宽资源,结果导致拥塞,这也是合理的,毕竟TCP看不到网络的状态,同时这也决定了TCP的拥塞控制必须采用试探性的方式,最终到达一个足以引起其“反应”的“刺激点”。

拥塞控制需要完成以下两个任务:1.公平性;2.拥塞之后退出拥塞状态。

● 疑难杂症16:影响拥塞的因素

我们必须认识到拥塞控制是一个整体的机制,它不偏向于任何TCP连接,因此这个机制内在的就包含了公平性。那么影响拥塞的因素都有什么呢?具有讽刺意味的是,起初TCP并没有拥塞控制机制,正是TCP的超时重传风暴(一个分段丢失造成后续的已经发送的分段均被重传,而这些重传大多数是不必要的)加重了网络的拥塞。因此重传必然不能过频,必须把重传定时器的超时时间设置的稍微长一些,而这一点在单一重传定时器的设计中得到了加强。除此TCP自身的因素之外,其它所有的拥塞都可以靠拥塞控制机制来自动完成。

另外,不要把路由器想成一种线速转发设备,再好的路由器只要接入网络,总是会拉低网络的总带宽,因此即使只有一个TCP连接,由于TCP的发送方总是以发送链路的带宽发送分段,这些分段在经过路由器的时候排队和处理总是会有时延,因此最终肯定会丢包的。

最后,丢包的延后性也会加重拥塞。假设一个TCP连接经过了N个路由器,前N-1个路由器都能顺利转发TCP分段,但是最后一个路由器丢失了一个分段,这就导致了这些丢失的分段浪费了前面路由器的大量带宽。

本新闻共6页,当前在第5页  1  2  3  4  5  6  

分享道
相关新闻