TCP的建立和关闭
复位报文段
- 在某些特殊的情况,TCP连接的一端会向另一端发送携带RST标志的报文段,即复位报文段,以通知对方关闭连接或重新建立连接。
- 收到复位报文段的一端应该关闭连接或重新连接,而不能回应这个复位报文段。
异常终止连接
- TCP提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。
TCP交互数据流
- TCP报文段所携带的应用程序数据按照长度分为两种:
- 交互数据
仅包含很少的字节。使用交互数据的应用程序或协议对实时性要求高。 - 成块数据
成块数据的长度通常则为TCP报文段允许的最大数据长度。使用成块数据的应用程序或协议对传输效率要求高。
- 交互数据
Nagle算法
- Nagle算法要求一个TCP连接的通信双方在任意时刻都最多只能发送一个未被确认的TCP报文段,在该TCP报文段的确认到达之前不能发送其他TCP报文段。
- 另一方面,发送方在等待确认的同时收集本端需要发送的微量数据,并在确认到来时以一个TCP报文段将他们全部发出。
- 这样极大的减少了网络上微小TCP报文段的数量。
TCP成块数据流
- 当传输大量大块数据的时候,发送方会连续发送多个TCP报文段,接收方可以一次确认所有这些报文段。至于能连续发送多少个TCP报文段,则是由接收通告窗口的大小决定的。
带外数据
- 有些传输层协议具有带外数据的概念,用于迅速通告对方本端发生的重要事件。
- UDP没有实现带外数据传输,TCP也没有真正的带外数据。
不过,TCP可以利用其头部中的紧急指针标志和紧急指针两个字段,给应用程序提供一种紧急方式。
TCP的紧急方式利用的是传输普通数据的连接来传输紧急数据。
TCP超时重传
- TCP服务必须能够重传超时时间内未收到确认的TCP报文段。
为此,TCP模块为每个TCP报文段都维护一个重传定时器,该定时器在TCP报文段第一次被发送时启动。
如果,超时时间内未收到接收方的应答,TCP模块将重传TCP报文段并重置定时器。 - Linux有两个重要的内核参数与TCP超时重传有关:
proc/sys/net/ipv4/tcp_retries1
,指定在底层IP接管之前TCP最少执行的重传次数,默认值是3。/proc/sys/net/ipv4/tcp_retries2
,指定了连接放弃前TCP最多可以执行的重传次数,默认值是15(一般对应13到30分钟)。
TCP拥塞控制
概述
- TCP模块还有一个重要的任务,就是提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。这就是所谓的拥塞控制。
- 拥塞控制的四个部分:
- 慢启动
- 拥塞避免
- 快速重启
- 快速恢复
- Linux下对拥塞控制有多种实现:reno、vegas、cubic等,它们或部分或全部实现了上述四个部分。
/proc/sys/net/ipv4/tcp_congestion_control
文件指示了机器当前所使用的拥塞控制算法。- 拥塞控制最终受控制变量是发送端向网络一次连续写入(收到其中第一个数据的确认之前)的数据量,称之为SWND(发送窗口)。
- 不过,发送端最终是以报文段来发送数据,所以SWND限定了发送端能连续发送的TCP报文段数量。
- 这些TCP报文段的最大长度(仅指数据部分),称为SMSS(发送者最大段大小),其值一般等于MSS。
- 发送端需要合理地选择SWND的大小,如果SWND太小,会引起明显的网络延迟;反之,如果SWND太大,则容易导致网络拥塞。
- 前面有提到,接收方可以通过其接收通告窗口(RWND)来控制发送端的SWND。但是显示是不够的,所以发送端引入了一个称为拥塞窗口(CWND)的状态变量。
实际的SWND值是RWND和CWND中较小者。
慢启动和拥塞避免
- TCP连接建立好之后,CWND将被设置成初始值IW(Initial Window),其大小为2到4个SMSS。但新的Linux内核提高了该初始值,以减小传输滞后。
此时发送端,最多能发送IW字节的数据。
此后发送端每收到接收端的一个确认,其CWND就按照下面公式增加:- CWND += min(N,SMSS)
- N是此次确认中包含的之前未被确认的字节数。这样一来,CWND将按照指数形式扩大,这就是所谓的慢启动。
- 慢启动算法的理由是,TCP模块刚开始发送数据时并不知道网络的实际情况,需要用一种试探的方式平滑地增加CWND的大小。
- 但是如果不施加其他的手段,慢启动必然使得CWND很快膨胀(可见慢启动并不慢),并最终导致网络拥塞。
因此TCP拥塞控制中定义了另一个重要的状态变量:慢启动门限。
当CWND的大小超过该值时,TCP拥塞控制将进入拥塞避免阶段。 - 拥塞避免算法使得CWND按照线性方式增加,从而减缓其扩大。
判断拥塞控制发生
- 传输超时,或者说TCP重传定时器溢出。
- 采用慢启动和拥塞避免。
- 接收到重复的确认报文段。
- 使用快速重传和快速恢复
- 如果发送端检测到拥塞发生是由于传输超时导致的,也就是第一种情况,那么将将执行重传并作出如下调整:
ssthresh=max(FlightSize/2, 2*SMSS)
CWND <= SMSS
- FlightSize是已经发送但未收到确认的字节数。这样调整之后,CWND将小于SMSS,那么也必然小于新的慢启动门限值ssthresh,故而拥塞控制再次进入慢启动阶段。
快速重传和快速恢复
- 很多情况下,发送端都可能接收到重复的确认报文段,比如TCP报文段丢失,或者接收端收到乱序TCP报文段并重排序等。拥塞控制算法需要判断当前收到重复的确认报文段时,网络是否真的发生了拥塞,或者说TCP报文段是否真的丢失了。
- 具体做法是:
发生端如果连续收到了3个重复的确认报文段,就认为是拥塞了。然后它启用快速重传和快速恢复算法来处理拥塞,过程如下:- 当收到第三个重复的确认报文段时,按照
ssthresh=max(FlightSize/2, 2*SMSS)
CWND <= SMSS
来计算出ssthresh,然后立即重传丢失的报文段,并按照CWND=ssthresh+3*SMSS
设置CWND。 - 每次收到一个重复的确认时,设置
CWND=CWND+SMSS
,此时发送端可以发送新的TCP报文段(如果新的CWND允许的话)。 - 当收到新数据的确认时,设置
CWND=ssthresh
。
- 当收到第三个重复的确认报文段时,按照
- 快速重传和快速恢复完成之后,拥塞控制将恢复到拥塞避免阶段。
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Cef:沙盒、CefApp、CefClient02/29
- ♥ Linux 进程描述&&相关介绍03/28
- ♥ WebSocket协议相关学习一03/24
- ♥ Linux_ 命令大全 文档编辑03/16
- ♥ Linux 高性能服务器编程:服务器程序规范12/04
- ♥ Vim编辑器的操作03/17