TCP/IP协议族学习笔记之流量控制

网络传输中的两个很现实的问题:发送方的发送速率和接收方的接受速率如果不匹配将导致问题:如果发送方的发送速率大于接收方的接受速率,那么接收方将来不及接受数据,从而导致数据丢失。如果发送方的发送速率小于接收方的接受速率,那么接收方需要等待发送方的数据,从而导致接收方性能降低。

流量控制针对的是第一个问题,即如何避免因接收方速率小于发送方而导致的数据丢失。

消息的推模式与拉模式

推模式指的是无论消耗方是否请求数据,数据一产生就进行推送。

拉模式指的是只在消耗方请求的时候才发数据。

对于拉模式,由于是在消耗方准备好接收的情形下进行的,因此无需进行流量控制。

而对于推模式,接收方没法及时处理到达的数据时,需要进行反向流量控制,即通知发送方“别发太快”。

传输层通信实体

传输层通信的四个实体:发送方进程,发送方传输层,接收方传输层,接收方进程。

应用层的发送方进程将数据发往发方传输层,发方传输层将数据封装成分组,发送到收方的传输层,收方传输层对分组进行解封并发给接收方的进程。

发方传输层、收方传输层既是生产者又是消费者,发方进程是生产者,收方进程为消费者。收方进程通常从收方传输层“拉取”数据。因此,需要进行流控的过程有:发方传输层到发方进程,收方传输层到发方传输层。注意流量控制是反向的。

通常可以使用缓存来进行流量控制:即在需要流控的消费者的那一端设置一个接收缓存。

此处,应在发方传输层和收方传输层各自设置一个缓存。当消费者的缓存满了,就通知生产者停止传送数据,等缓存不满的时候再通知生产者发送数据。

扫描二维码关注公众号,回复: 1052422 查看本文章

这样一来,需要在发方传输层设置一个缓存,用于发方传输层到发方进程的流控;在接收方传输层设置一个缓存,用于收方传输层到发方传输层的流控。

可以说流控中,发方的传输层控制了发方进程,收方的传输层控制了发方的传输层。

对于发方传输层到发方进程的流控,只要发方传输层的窗口满了,就拒绝接收发方进程的数据。

对于收方传输层到发方传输层的流控,比较复杂:用一个书上的例子来描述


简单起见,认为只存在客户到服务器的单向通信。因此每端值有一个窗口。

1,一开始客户端向服务器发起连接请求,发送了SYN握手信号,并且假设其序号为100。

2,服务器收到握手信号以后,设置一个接受窗口,假设其大小为800字节(不超过65535),并且窗口的第一个字节的序号为101.服务器向客户端发送一个SYN+ACK,包含了自己的序列号1001,以及ACK(客户端期待收到的下一个字节的序号),同时在接收窗口字段中填入自己的窗口大小。

3,客户端收到服务器的SYN+ACK响应以后,设置一个窗口大小为800字节的发送窗口。并发送ACK给服务器。服务器收到ACK以后,三次握手结束,连接创建完毕。

4,客户端开始发送数据给服务器了,假设发送了200字节,分组达到了服务器。

5,服务器看到了200字节,填入自己的接收缓存中,并将窗口设置为800-200 = 600字节、同时回复客户端一个ACK,以及自己当前的窗口大小600。客户端收到ACK以后,知道发送的200字节被成功接收了,同时将之前发送过的200字节数据清除出缓存,并对比收到的窗口大小,设置发送窗口大小为600。

6,客户端继续发了300字节给服务器,服务器收到了300字节,同时服务器的应用进程从服务器传输缓存中拉取了100字节,此时,服务器发送ACK给客户端,并将当前窗口大小更新为600-300+100 = 400字节。

7,客户端收到服务器的ACK以后,将之前发送过的300字节数据清除出缓存,并知道了服务器此时的窗口大小为400,就将自己的发送窗口设置为400。

8,服务器的应用层进程又从服务传输层缓存中拉取了200字节数据,服务器更新自己的窗口大小为400+200=600字节,发送一个ACK给客户端。客户端收到这个ACK以后,更新自己的发送窗口为600字节。

糊涂窗口综合征

如果发方应用进程发送数据很慢或者接收进程消耗数据很慢会导致性能问题,糟糕的情况是每次只发一个字节。而报文段首部(TCP、IP)加起来有40字节。这样额外开销达到了41/1,网络容量效率很低。这种现象就叫做糊涂窗口综合征。

对于发送方进程产生数据很慢的情形,可以让TCP收集数据到一定程度再发,而不是一个一个字节发。但是也不能让TCP等太久,等久了也会降低处理性能。处理此类问题用到了经典的Nagle算法。

Nagle算法:

1,发方的TCP将从发方应用进程接收到的第一块数据发送出去,哪怕只有一个字节。

2,发方TCP等待收方的ACK,收到ACK之前积累数据,不发送。等到收到ACK以后(或者积累到65535字节)才将积累的数据一并发出去。

3,对于剩下的传输,重复2的过程。

对于接收方进程消耗数据很慢的情形,借鉴前面的思路,可以让收方等到接受窗口足够大的时候再通知发送方发数据。经典的算法有Clark算法和推迟确认。

CLark算法:收方只要有数据到达就发送ACK,但是接收方的TCP缓存窗口值要足够大才通知非零窗口值,否则通知发方窗口大小为0。

推迟确认:收方收到了数据,暂时不发送ACK,而是等到自己的TCP缓存窗口值足够大的时候才发送确认。在此之前,发送方不会发送数据。

推迟确认的优点:减小了通信量,收方无需对每一个报文段进行确认。缺点:推迟太久导致发送方重传未被确认的报文段。

TCP将推迟确认的时间上限设定为500ms。





猜你喜欢

转载自blog.csdn.net/u012260341/article/details/79769105