TCP的成块数据流
引言
一种流量控制方法——滑动窗口协议
该协议允许发送方在停止并等待确认前可以连续发送多个分组,由于发送发不必每发送一个分组就停下来等待确认,因此该协议可以加速数据的传输。
正常数据流
隔一个报文段确认的策略
- 每2个报文段返回一次ACK。
- 如果定时器溢出,那不管有没有确认2个报文段,也返回一次ACK。
ACK是积累的
使用TCP的滑动窗口协议时,接收方不必确认每一个收到的分组,在TCP中,ACK是积累的——它们表示接收到已经正确收到了一直到确认序号减1的所有字节。
下图是传输8192字节的一种时间序列
发送同一段数据可能有不同的时间序列
- 由于发送方和接收方处理数据的能力不同,那么时间序列也可能不同。
- 比如接收方处理得慢,那么发送方必须等到接收方处理完窗口里面的数据才能发送。
- 如果接收方的缓冲区数据满了,会返回一个ACK,并通知窗口为0.
- 过一段时间缓冲区有位置了,会再发一个ACK通知窗口大小。(并不是有位置就马上通知)
滑动窗口
接收方通告的窗口称为“提供的窗口”(通告窗口),表示对面有那么多个位置可以接收礼物啊,快把东西丢过去呀。
然后发送方知道还有6个位置,所以发了4~6一共3个鱼丸过去,对面还有3个位置,现在还能发送3个。
窗口移动:
- 左边沿往右移成为窗口合拢。也就是发送出去的窗口被确认,但是对面可用的窗口位置没有增多。
- 右边沿向右移动称为窗口张开。也就是对面已经处理了缓冲区的数据,又腾出地方可以让你送鱼丸了。
- 右边沿向左移动称为窗口收缩。强烈建议不使用这种方式。
如果左边沿到达右边沿,则称其为一个零窗口,此时发送方一般不能再发送数据报。
总结:
- 发送方不必发送一个全窗口大小的数据。
- 来自接收方的一个ACK并把窗口右移,因为窗口的大小是相对于确认序号的。(这个想想就理解了)
- 窗口大小可以减小,但是右边沿不能左移。
- 接收方返回一个ACK前不必等待窗口被填满才返回。(应该可以设定的,例如前面提到的“隔一个报文段确认”)
窗口大小
默认为4096,但是并非最理想的。16384字节可以增加约40%的吞吐量。
PUSH标志
该标志通知接收方将所收到的数据全部提交给接收进程。这里的数据包括与PUSH一起传送的数据以及接收方TCP已经为接收进程收到的其它数据。
同时也会将发送缓冲区里面的数据立即发送出去。
慢启动(重点)
如果在发送方和接收方之间存在多个路由器和速度较慢的链路时(广域网),一开始就不断发送报文段直至达到接收方的窗口满为止,这样的行为可能导致拥塞。
慢启动算法(slow start)通过观察到新分组进入网络的速率应该与另一端返回确认的速率相同而进行工作。
慢启动需要加入一个新的窗口概念——拥塞窗口,cwnd.
拥塞窗口初始化为1个报文段,每接收到一个ACK就增加一个报文段。(cwnd以字节为单位,但是慢启动以报文段大小为单位,也就是1个报文段。)
大小变化:1->2->4->8…… 可以看出拥塞窗口的大小是以指数方式增长的。
发送方取拥塞窗口与通告窗口的最小值作为发送上限。(就是你能发送的大小和对方能接收的大小的最小值)
在某些点上可能达到了互联网的容量,于是中间路由器开始丢弃分组,这就通知发送方它的拥塞窗口开得过大。(流量控制)
成块数据的吞吐量
发送方和接收方之间的路径称为管道。
带宽时延乘积 capacity(bit)=bandwidth(b/s) x round-trip time(s)
通道容量=带宽 x 往返时间 (容量=时间 x 速度)也就是整个通道能装下的容量大小
紧急方式
“紧急方式”使一端可以告诉另一端有些具有某种方式的“紧急数据”已经放置在普通的数据流中,接收方收到通知,并决定如何处理。
可以通过设置TCP首部中的两个字段来发出这种从一端到另一端的紧急数据已经被放置在数据流中的通知。URG比特被置为1,并且一个16bit的紧急指针放置为一个正的偏移量,该偏移量必须与TCP首部中的序号字段相加,以便得出紧急数据的最后一个字节的序号。
当紧急数据进入发送缓冲区后,下一个将要发送的数据(可能是紧急,也可能不是)的URG比特置为1,发送给接收方。接收方知道后就知道发送方处于紧急状态(仅仅知道而已,不会采取什么措施,它会通知应用层现在有紧急数据,你自己看着办),直到接收到最后一个字节的紧急数据后解除这种状态。
如果接收方通告窗口为0,那么数据无法发送出去,但是URG比特这个报文还是会发送出去,通知对面我这边有紧急数据。