TCP/IP 详解卷一学习笔记(五):TCP 成块数据流

时间:2023-01-08 09:29:03

目录:

经受时延的确认

Nagle算法

滑动窗口

慢启动

窗口大小

1.经受时延的确认

如果tcp对每个数据包都发送一个ack确认,那么只是一个单独的数据包为了发送一个ack代价比较高,所以tcp会延迟一段时间,如果这段时间内有数据发送到对端,则捎带发送ack,如果在延迟ack定时器触发时候,发现ack尚未发送,则立即单独发送。

对于小的报文段,通常TCP在接收到数据时并不立即发送ACK;相反,它推迟发送,以便将ACK与需要沿该方向发送的数据一起发送(有时称这种现象为数据捎带ACK)。

绝大多数实现采用的时延为200 ms,也就是说,TCP将以最大200 ms 的时延等待是否有数据一起发送 。

2.Nagle算法

在局域网上,小分组通常不会引起麻烦,因为局域网一般不会出现拥塞。但在广域网上,这些小分组则会增加拥塞出现的可能。一种简单和好的方法就是采用Nagle算法。

该算法要求一个 TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组。相反,TCP收集这些少量的分组,并在确认到来时以一个分组的方式发出去。

该算法的优越之处在于它是自适应的:确认到达得越快,数据也就发送得越快。而在希望减少微小分组数目的低速广域网上,则会发送更少的分组。

关闭Nagle算法

对于实时性要求比较高的应用,我们也需要关闭Nagle算法。如果TCP每次得到一个字符,它很可能会发送序列中的第一个字符,然后缓存其他字符并等待对该字符的确认。但当服务器接收到该字符后,它并不发送确认,而是继续等待接收序列中的其他字符。这就会经常触发服务器的经受时延的确认算法,表示剩下的字符没有在200 ms内发送。对交互用户而言,这将产生明显的时延。
可以考虑关闭Nagle算法;或者使用writev函数,缓存多个数据后再发送。TCP_NODELAY选项来关闭Nagle算法。

3.滑动窗口

TCP使用滑动窗口协议作为流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。

使用TCP的滑动窗口协议时,接收方不必确认每一个收到的分组。在TCP中,ACK是累积的—它们表示接收方已经正确收到了一直到确认序号减1的所有字节。

TCP/IP 详解卷一学习笔记(五):TCP 成块数据流

接收方通告的窗口称为提供的窗口(offered window),它覆盖了从第4字节到第10字节的区域,表明接收方已经确认了包括第3字节在内的数据,且通告窗口大小为 7。当接收方确认数据后,这个滑动窗口不时地向右移动。窗口两个边沿的相对运动增加或减少了窗口的大小。我们使用三个术语来描述窗口左右边沿的运动:

1)窗口合拢:窗口左边沿向右边沿靠近。这种现象发生在数据被发送和确认时。

2)窗口张开:窗口右边沿向右移动时将允许发送更多的数据。这种现象发生在另一端的接收进程读取已经确认的数据并释放了TCP的接收缓存时。

3)窗口收缩:窗口右边沿向左移动。

TCP/IP 详解卷一学习笔记(五):TCP 成块数据流

窗口的左边沿受另一端发送的确认序号的控制,不可能向左边移动。因此如果接收到一个指示窗口左边沿向左移动的ACK,则它被认为是一个重复ACK,并被丢弃。
如果左边沿到达右边沿,则称其为一个零窗口,此时发送方不能够发送任何数据。

TCP/IP 详解卷一学习笔记(五):TCP 成块数据流

建立连接的前3个报文段中显示了每一端MSS的值,以及窗口大小win。

发送方首先传送3个数据报文段(4~6)。下一个报文段(7)仅确认了前两个数据报文段。

报文段7的ACK的序号之所以是2049而不是3073是由以下原因造成的:三个报文段4、5和6依次到达并按接收顺序放到IP的输入队列。IP将按同样顺序将它们交给TCP。当TCP处理报文段4时,该连接被标记为产生一个经受时延的确认。TCP处理下一报文段(5),由于TCP现在有两个未完成的报文段需要确认,因此产生一个序号为2049的ACK(报文段7),并清除该连接产生经受时延的确认标志。

报文段7中的窗口大小为 2048,表明在TCP的接收缓存中还有2048个字节的数据等待被应用程序读取。

报文段9确认了最后发送的数据,但通告窗口大小为2048,同样表示接收缓存还有2048个数据等待被应用程序读取。

报文段10看起来像一个ACK,但并不确认任何新数据,只是用作窗口更新。

总结:

1) 发送方不必发送一个全窗口大小的数据。

2) 来自接收方的一个报文段确认数据并把窗口向右边滑动。这是因为窗口的大小是相对于确认序号的。

3) 窗口的大小可以减小,但是窗口的右边沿却不能够向左移动。

4) 接收方在发送一个 ACK前不必等待窗口被填满。许多实现每收到两个报文段就会发送一个ACK。

4.慢启动

发送方一开始便向网络发送多个报文段,直至达到接收方通告的窗口大小为止。当发送方和接收方处于同一个局域网时,这种方式是可以的。但是如果在发送方和接收方之间存在多个路由器和速率较慢的链路时,就有可能出现一些问题。一些中间路由器必须缓存分组,并有可能耗尽存储器的空间。

慢启动为发送方的TCP增加了另一个窗口:拥塞窗口(congestion window),记为cwnd。当与另一个网络的主机建立TCP连接时,拥塞窗口被初始化为1个报文段(即另一端通告的报文段大小)。每收到一个ACK,拥塞窗口就增加一个报文段(cwnd以字节为单位,但是慢启动以报文段大小为单位进行增加)。

发送方取拥塞窗口与通告窗口中的最小值作为发送上限。拥塞窗口是发送方使用的流量控制,而通告窗口则是接收方使用的流量控制。

发送方开始时发送一个报文段,然后等待 ACK。当收到该ACK时,拥塞窗口从1增加为2,即可以发送两个报文段。当收到这两个报文段的ACK时,拥塞窗口就增加为4。这是一种指数增加的关系。

5.窗口大小

窗口大小、窗口流量控制以及慢启动对传输成块数据的TCP连接的吞吐量的相互作用。

TCP/IP 详解卷一学习笔记(五):TCP 成块数据流  

在时间31及其后续时间,发送方和接收方之间的管道( pipe )被填满。每当接收方在某一个时间单位从网络上移去一个报文段,发送方就再发送一个报文段到网络上。但是不管有多少报文段填充了这个管道,返回路径上总是具有相同数目的ACK。这就是连接的理想稳定状态。

作为最大的吞吐量,发送方在任何时候有8个已发送的报文段未被确认。接收方的通告窗口必须不小于这个数目。

带宽时延乘积

通道容量:

capacity(bit) =bandwidth(b/s)×round-trip time(s)

这个值依赖于网络速度和两端的往返时间RTT