TCP 流量控制与拥塞控制

TCP的特点

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的。为了通过IP数据报实现可靠性传输,需要考虑很多事情,侧如数据的破坏、丢包、重复以及分片顺序混乱等问题。如不能解决这些问题,也就无从谈起可靠传输。TCP通过校验和、序列号、确认应答、重发控制、连接管理、以及窗口控制等机制来实现可靠性传输。TCP建立连接的实质是,主机A和主机B告知彼此的第一个发送字节的初始序列号,建立连接后对每一个发送的字节都需要以初始序列号为基点进行编号,需要对方来确认每一个字节编号都已经成功接收,双方初始序列号是由操作系统动态生成的随机的值,一般每个TCP 会话都会有不一样的初始序列号,占四个字节。

TCP 流量控制与拥塞控制_第1张图片
TCP.png

ACK

TCP通过肯定的确认应答(ACK) 实现可靠的数据传输。当发送端将数据发出之后会等待对端的确认应答。如果有确认应答,说明数据已经成功到达对端。反之,则数据丢失的可能性很大。在一定时间内没有等到确认应答,发送端就可以认为数据已经丢失,并进行重发由此,即使产生了丢包,仍然能够保证数据能够到达对端,实现可靠传输。如果数据被重发之后若还是收不到确认应答,则进行再次发送。此时确认应答的时间将会以2倍、4信的指数函数延长。达到一定次数后,如果任没有任何确认应答返回,就会判断为网络发生异常,强制关闭连接,并且通知应用通信异常强行终止。

流控制

发送端根据自己的实际情况发送数据。但是,接收端可能收到的是一个毫无
关系的数据包又可能会在处理其他问题上花费一些时间。因此在为这个数据包做其他处理时会耗费一些时间,甚至在高负荷的情况下无法接收任何数据。如此一来,如果接收端将本应该接收的数据丢弃的话,就又会触发重发机制,从而导致网络流量的无端浪费。为了防止这种现象的发生,TCP 提供一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量。这就是所谓的流控制。它的具体操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不超过这个限度的数据。该大小限度就被称作窗口大小。在前面6.4.6 节中所介绍的窗口大
小的值就是由接收端主机决定的。TCP 首部中,专门有一个字段用来通知窗口大小。接收主机将自己可以接收的缓冲区大小放人这个字段中通知给发送端。这个字段的值越大,说明网络的吞吐量越高。不过,接收端的这个缓冲区一旦面临数据溢出时,窗口大小的值也会随之被设置为一个更小的值通知给发送端,从而控制数据发送量。也就是说,发送端主机会根据接收端主机的指示,对发送数据的量进行控制。这也就形成了一个完整的TCP 流控制(流量控制)。

拥塞控制

因为 TCP 的窗口控制,收发主机之间即使不再以一个数据段为单位发送确认应答,也能够连续发送大量数据包。然而,如果在通信刚开始时就发送大量数据,也可能会引发其他问题。一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。在网络出现拥堵时,如果突然发送一个较大量的数据,极有可能会导致整个网络的瘫痪。TCP 为了防止该问题的出现,在通信一开始时就会通过一个叫做慢启动的算法得出的数值,对发送数据量进行控制。首先,为了在发送端调节所要发送数据的量,定义了一个叫做“拥塞窗口”的概念。于是在慢启动的时候,将这个拥塞窗口的大小设置为1个数据段发送数据,之后每收到一次确认应答(ACK),拥塞窗口的值就加1MSS。在发送数据包时,将拥塞窗D的大小与接收端主机通知的窗口大小做比较,然后按照它们当中较小那个值,发送比其还要小的数据量。如果重发采用超时机制,那么拥塞窗口的初始值可以设置为1以后再进行慢启动修正。有了上述这些机制,就可以有效地减少通信开始时连续发包导致的网络拥堵,还可以避免网络拥塞情况的发生。

慢启动

慢启动算法的基本思想是当TCP开始在一个网络中传输数据或发现数据丢失并开始重发时,首先慢慢的对网路实际容量进行试探,避免由于发送了过量的数据而导致阻塞。主机发送了一个报文后就要停下来等待应答,每收到一个应答,拥塞窗口就增加一段长度,直至等于设定的阈值。比如我们可以先让发送方发一个包,等这个包被 ack 之后,我们再发 2 个包,这 2 个被 ack 之后再发 4 个包,以此类推,让一次所发的包数量慢慢增加,这就是慢启动。

Window

谈 TCP 离不开 窗口的概念,有 congestion window,receive window,sliding window 等等。window 是以 tcp segment 数量为单位,我们可以说当前 window 值由几个 tcp 包构成,而当我们说 window size 的时候,又是在说一个 window 所包含的字节数。window size 除了和 tcp segment 的数量有关之外,还和单个 tcp segment 的最大 size 有关,即 MSS 值。发送方的 Window 大小称之为 CWND(congestion window),接收方的 Window 大小称之为 RWND(receiver window,或 advertised window)。CWND 表示当前发送方可以发送多少个 TCP 包,而 RWND 表示当前接收方还能接收多少个 TCP 包。值得注意的是,CWND 是一个发送方本地的值,并不会在网络上传输。而 RWND 则是由接收方告知发送方的,是存在于 TCP 包的协议中,会通过网络传输。比如,A主机发送给B window 大小为8192,意思是:B主机最多可以连续发送8192 字节给A主机(一般来说,8192字节就是A主机的接收缓冲区大小),如果B主机不小心发送超过8192字节,如果application 没有及时取走,则超过 8192 自己数据可能会因为A主机的接收缓冲区满而被丢弃,所以B主机会严格遵守A的 RWND 的大小,如果A主机通告它的window大小为 0,则B主机一定不会发送数据。TCP首部中 Window Size 占两个byte,最大值为65535。

TCP 流量控制与拥塞控制_第2张图片
TCP首部.jpg

MTU

MTU: Maximum Transmit Unit,最大传输单元,即物理接口(数据链路层)提供给其上层(通常是IP层)最大一次传输数据的大小;以普遍使用的以太网接口为例,缺省MTU=1500 Byte,这是以太网接口对IP层的约束,如果IP层有<=1500 byte 需要发送,只需要一个IP包就可以完成发送任务;如果IP层有> 1500 byte 数据需要发送,需要分片才能完成发送,这些分片有一个共同点,即IP Header ID相同。

MSS

MSS:Maximum Segment Size ,TCP提交给IP层最大分段大小,不包含TCP Header和 TCP Option,只包含TCP Payload ,MSS是TCP用来限制application层最大的发送字节数。如果底层物理接口MTU= 1500 byte,则 MSS = 1500- 20(IP Header) -20 (TCP Header) = 1460 byte,如果application 有2000 byte发送,需要两个segment才可以完成发送,第一个TCP segment = 1460,第二个TCP segment = 540。

Persist Timer

Persist Timer: 用于周期探测对方receiver window size 是否依然为0的定时器。比如,A主机通告它的window大小为 0,则B一定不会发送数据。B主机也不会一直等下去,如果一直等下去则会发生死锁。为了防止这种情况的死锁发生,发送者使用了一个持续计时器(persiet timer)来周期性的询问接收者是否已增加了窗口。从发送者发出的这些段称为窗口探测(window probes)。

tcpdump

在iOS设备上抓包比较方便,除了常用的,如:Charles、Paw 等软件外,我们还可以使用tcpdump。以下是抓包的步骤:

  • 1、先将iPhone用数据线连到你的Mac设备;

  • 2、通过各类助手或者iTunes获取iPhone的UDID;

  • 3、通过Mac上的rvictl程序,创建一个虚拟网卡,然后通过这个虚拟网卡监听设备上所有的网络流量。终端命令 rvictl -s udid

  • 启动tcpdump。终端命令:sudo tcpdump -i rvi0 -AAl ( rvi0 为创建的虚拟网卡)。



(待续)

你可能感兴趣的:(TCP 流量控制与拥塞控制)