计算机网络 第五章:运输层
1.运输层协议概述
1.1 进程之间的通信
通信的真正端点并不是主机而是主机中的进程。运输层为应用进程之间提供端到端的逻辑通信,运输层还要对收到的报文进行差错检测。
当运输层采用面向连接的 TCP 协议时,尽管下面的网络是不可靠的(只提供尽最大努力服务),但这种逻辑通信信道就相当于一条全双工的可靠信道。但当运输层采用无连接的 UDP 协议时,这种逻辑通信信道仍然是一条不可靠信道。
1.2 运输层的两个主要协议
TCP/IP 运输层的两个主要协议都是互联网的正式标准,即:
- 用户数据报协议 UDP (User Datagram Protocol) [RFC 768]
- 传输控制协议 TCP (Transmission Control Protocol) [RFC 793]
UDP 在传送数据之前不需要先建立连接。远地主机的运输层在收到 UDP 报文后,不需要给出任何确认。虽然 UDP 不提供可靠交付,但在某些情况下 UDP 却是一种最有效的工作方式。
TCP 则提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP 不提供广播或多播服务。由于 TCP 要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多的开销,如确认、流量控制、计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多的处理机资源。
1.3 运输层的端口
运输层使用协议端口号(protocol port number),或通常简称为端口(port)。虽然通信的终点是应用进程,但只要把所传送的报文交到目的主机的某个合适的目的端口,剩下的工作(即最后交付目的进程)就由 TCP 或 UDP 来完成。
由此可见,两个计算机中的进程要互相通信,不仅必须知道对方的 IP 地址(为了找到对方的计算机),而且要知道对方的端口号(为了找到对方计算机中的应用进程)。
1.3.1 服务器端使用的端口号
熟知端口号(系统端口号):数值为0~1023。这些数值可在网址 www.iana.org 查到。IANA 把这些端口号指派给了 TCP/IP 最重要的一些应用程序,让所有的用户都知道。当一种新的应用程序出现后,IANA 必须为它指派一个熟知端口,否则互联网上的其他应用进程就无法和它进行通信。
1.3.2 客户端使用的端口号
客户端使用的端口号(短暂端口号):数值为 49152~65535。由于这类端口号仅在客户进程运行时才动态选择,因此又叫做短暂端口号。通信结束后,刚才已使用过的客户端口号就不复存在,这个端口号就可以供其他客户进程使用。
2.用户数据报协议 UDP
2.1 UDP 概述
用户数据报协议 UDP 只在 IP 的数据报服务之上增加了很少一点的功能,这就是复用和分用的功能以及差错检测的功能。UDP的主要特点是:
UDP 是无连接的,即发送数据之前不需要建立连接(当然,发送数据结束时也没有连接可释放),因此减少了开销和发送数据之前的时延。
UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表(这里面有许多参数)。
UDP 是面向报文的。发送方的 UDP 对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP 对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这就是说,应用层交给 UDP 多长的报文,UDP 就照样发送,即一次发送一个报文。
UDP 没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。
UDP 支持一对一、一对多、多对一和多对多的交互通信。
UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部要短。
2.2 UDP 的首部格式
用户数据报 UDP 有两个字段:数据字段和首部字段。
首部字段很简单,只有 8 个字节,由 4个 字段组成,每个字段的长度都是 2 个字节。各字段意义如下:
- 源端口:源端口号。在需要对方回信时选用。不需要时可用全 0。
- 目的端口:目的端口号。这在终点交付报文时必须使用。
- 长度:UDP 用户数据报的长度,其最小值是 8(仅有首部)。
- 检验和:检测 UDP 用户数据报在传输中是否有错。有错就丢弃。
3.传输控制协议 TCP 概述
3.1 TCP 最主要的特点
TCP 是 TCP/IP 体系中非常复杂的一个协议。下面介绍 TCP 最主要的特点:
TCP 是面向连接的运输层协议。这就是说,应用程序在使用 TCP 协议之前,必须先建立 TCP 连接。在传送数据完毕后,必须释放已经建立的 TCP 连接。
每一条 TCP 连接只能有两个端点(endpoint),每一条 TCP 连接只能是点对点的(一对一)。
TCP 提供可靠交付的服务。通过 TCP 连接传送的数据,无差错、不丢失、不重复,并且按序到达。
TCP 提供全双工通信。
面向字节流。TCP 中的 “流”(stream) 指的是流入到进程或从进程流出的字节序列。“面向字节流”的含义是:虽然应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。TCP 并不知道所传送的字节流的含义,也不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系(例如,发送方应用程序交给发送万的 TCP 共 10个数据块,但接收方的 TCP 可能只用了 4 个数据块就把收到的字节流交付上层的应用程序)。但接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。
3.2 TCP 的连接
TCP连接的端点叫做套接字(socket)或插口。根据 RFC 793 的定义:端口号拼接到 IP 地址即构成了套接字。因此,套接字的表示方法是在点分十进制的 IP 地址后面写上端口号,中间用冒号或逗号隔开。
$$
套接字 socket = (IP地址:端口号)
$$
每一条 TCP 连接唯一地被通信两端的两个端点(即两个套接字)所确定。即:
$$
TCP连接::= {socket_1,socket_2}= {(IP_1: port_1),(IP_2: port_2)}
$$
同一个 IP 地址可以有多个不同的 TCP 连接,而同一个端口号也可以出现在多个不同的 TCP 连接中。
4.可靠传输的工作原理
TCP 发送的报文段是交给 IP 层传送的。但 IP 层只能提供尽最大努力服务。因此,TCP 必须采用适当的措施才能使得两个运输层之间的通信变得可靠。
理想的传输条件有以下两个特点:
- 传输信道不产生差错。
- 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。在这样的理想传输条件下,不需要采取任何措施就能够实现可靠传输。
4.1 停止等待协议
“停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。
4.1.1 无差错情况
4.1.2 出现差错
分组在传输过程中出现差错的情况。在这两种情况下,B都不会发送任何信息。
注意三点:
- A 在发送完一个分组后,必须暂时保留已发送的分组的副本(在发生超时重传时使用)。只有在收到相应的确认后才能清除暂时保留的分组副本。
- 分组和确认分组都必须进行编号。这样才能明确是哪一个发送出去的分组收到了确认,而哪一个分组还没有收到确认。
- 超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些。如果重传时间设定得很长,那么通信的效率就会很低。但如果重传时间设定得太短,以致产生不必要的重传,就浪费了网络资源。
4.1.3 确认丢失和确认迟到
B 所发送的对 M1 的确认丢失了。A 在设定的超时重传时间内没有收到确认,并无法知道是自己发送的分组出错、丢失,或者是 B 发送的确认丢失了。因此 A 在超时计时器到期后就要重传 M1。现在应注意 B 的动作。假定 B 又收到了重传的分组M1。这时应采取两个行动:
- 丢弃这个重复的分组 M1,不向上层交付。
- 向 A 发送确认。不能认为已经发送过确认就不再发送,因为 A 之所以重传 M1 就表示 A 没有收到对 M1 的确认。
4.1.4 信道利用率
停止等待协议的优点是简单,但缺点是信道利用率太低。
4.2 连续 ARQ 协议
滑动窗口协议比较复杂,是 TCP 协议的精髓所在。
在讨论滑动窗口时,我们应当注意到,图中还有一个时间坐标(但以后往往省略这样的时间坐标)。按照习惯,“向前”是指“向着时间增大的方向”,而“向后”则是“向着时间减少的方向”。分组发送是按照分组序号从小到大发送的。
连续 ARQ 协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。接收方一般都是采用累积确认的方式。这就是说,接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已正确收到了。
累积确认有优点也有缺点。优点是:容易实现,即使确认丢失也不必重传。但缺点是:不能向发送方反映出接收方已经正确收到的所有分组的信息。
5.TCP 报文段的首部格式
TCP 虽然是面向字节流的,但 TCP 传送的数据单元却是报文段。一个 TCP 报文段分为首部和数据两部分,而 TCP 的全部功能都体现在它首部中各字段的作用。
首部固定部分各字段的意义如下:
源端口和目的端口:各占2个字节,分别写入源端口号和目的端口号。
序号:占 4 字节。序号范围是 $[0,2^{32} - 1]$,共 $2^{32}$(即4 294 967296)个序号。用完后,下一个序号就又回到 0。
确认号:占 4 字节,是期望收到对方下一个报文段的第一个数据字节的序号。
数据偏移:占 4 位,它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。这个字段实际上是指出 TCP 报文段的首部长度。
保留:占 6 位,保留为今后使用,但目前应置为 0。
紧急 URG (Urgent):当 URG=1 时,表明紧急指针字段有效。表此报文段中有紧急数据,应尽快传送。
确认 ACK:仅当 ACK=1 时确认号字段才有效。
推送 PSH:PSH=1 的报文段,就尽快地(即“推送”向前)交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。
复位 RST:当 RST=1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
同步 SYN:在连接建立时用来同步序号。当 SYN=1 而 ACK=0 时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使 SYN=1 和 ACK=1。因此,SYN 置为 1 就表示这是一个连接请求或连接接受报文。
终止 FIN:FIN=1 用来释放一个连接。
窗口:占 2 字节。窗口值是 $[0,2^{16} -1]$ 之间的整数。从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(以字节为单位)。
💡 例如,发送了一个报文段,其确认号是 701,窗口字段是 1000。这就是告诉对方:“从701号算起,我(即发送此报文段的一方)的接收缓存空间还可接收 1000 个字节数据(字节序号是701~1700),你在给我发送数据时,必须考虑到这一点。”
检验和:占 2 字节。检验和字段检验的范围包括首部和数据这两部分。
紧急指针:占 2 字节。紧急指针仅在 URG=1 时才有意义
选项:长度可变,最长可达 40 字节。
TCP 最初只规定了一种选项,即最大报文段长度 MSS(Maximum Segment Size))[RFC879]。MSS 是每一个 TCP 报文段中的数据字段的最大长度。数据字段加上 TCP 首部才等于整个的 TCP 报文段。所以 MSS 并不是整个 TCP 报文段的最大长度,而是 “TCP报文段长度减去TCP首部长度”。
MSS 与接收窗口值没有关系。若选择较小的MSS 长度,网络的利用率就降低。因此,MSS应尽可能大些,只要在IP层传输时不需要再分片就行。
6.TCP 可靠传输的实现
6.1 以字节为单位的滑动窗口
TCP 的滑动窗口是以字节为单位的。
发送窗口前沿通常是不断向前移动,但也有可能不动。但 TCP 的标准强烈不赞成向后收缩,因为很可能发送方在收到这个通知以前已经发送了窗口中的许多数据,现在又要收缩窗口,不让发送这些数据,这样就会产生一些错误。
- P3-P1 = A 的发送窗口
- P2-P1 = 已发送但尚未收到确认的字节数
- P3-P2 = 允许发送但当前尚未发送的字节数(又称为可用窗口或有效窗口)
未按序收到,窗口可以增大:
A 的发送窗口已满,可用窗口已减小到零,因此必须停止发送:
下图画出了发送方维持的发送缓存和发送窗口,以及接收方维持的接收缓存和接收窗口。这里首先要明确两点:
- 缓存空间和序号空间都是有限的,并且都是循环使用的。最好是把它们画成圆环状的。但这里为了画图的方便,我们还是把它们画成长条状的。
- 第二,由于实际上缓存或窗口中的字节数是非常之大的,因此上图仅仅是个示意图,没有标出具体的数值。但用这样的图来说明缓存和发送窗口以及接收窗口的关系是很清楚的。
再强调以下四点:
- 虽然 A 的发送窗口是根据 B 的接收窗口设置的,但在同一时刻,A 的发送窗口并不总是和 B 的接收窗口一样大。这是因为通过网络传送窗口值需要经历一定的时间滞后(这个时间还是不确定的)。另外,发送方 A 还可能根据网络当时的拥塞情况适当减小自己的发送窗口数值。
- 对于不按序到达的数据应如何处理,TCP 标准并无明确规定。如果接收方把不按序到达的数据一律丢弃,那么接收窗口的管理将会比较简单,但这样做对网络资源的利用不利(因为发送方会重复传送较多的数据)。因此TCP通常对不按序到达的数据是先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程。
- TCP 要求接收方必须有累积确认的功能,这样可以减小传输开销。接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。但请注意两点:
- 一是接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网络的资源。TCP 标准规定,确认推迟的时间不应超过 0. 5秒。若收到一连串具有最大长度的报文段,则必须每隔一个报文段就发送一个确认 [RFC 1122]。
- 二是捎带确认实际上并不经常发生,因为大多数应用程序很少同时在两个方向上发送数据。
- 最后再强调一下,TCP 的通信是全双工通信。通信中的每一方都在发送和接收报文段。因此,每一方都有自己的发送窗口和接收窗口。在谈到这些窗口时,一定要弄清是哪一方的窗口。
6.2 超时重传时间的选择
TCP 采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间 RTT。TCP 保留了 RTT 的一个加权平均往返时间 RTTs (这又称为平滑的往返时间,S 表示 Smoothed。因为进行的是加权平均,因此得出的结果更加平滑)。每当第一次测量到 RTT 样本时,RTTs 值就取为所测量到的 RTT 样本值。但以后每测量到一个新的 RTT 样本,就按下式重新计算一次 RTTs:
$$
新的RTTs = (1-a) ×(旧的RTTs)+ α ×(新的RTT样本)
$$
在上式中,0≤a<1,若:
- α 接近于 0,表示新的 RTTs 值和旧的 RTTs 值相比变化不大,而对新的 RTT 样本影啊个大 (RTT 更新校慢)
- α 接近于 1,则表示新的 RTTs 值受新的 RTT 样本的影响较大(RTT值更新较快)
显然,超时计时器设置的超时重传时间 RTO(RetransmissionTime-Out)应略大于上面得出的加权平均往返时间 RTTs:
$$
RTO=RTT_S+4× RTT_D
$$
而 $RTT_D$ 是 RTT 的偏差的加权平均值,它与 RTTs 和新的 RTT 样本之差有关。当第一次测量时,$RTT_D$ 值取为测量到的 RTT 样本值的一半。在以后的测量中,则使用下式计算加权平均的 $RTT_D$ :
$$
新的RTT_D=(1-β)×(旧的RTT_D)+βx|RTTs-新的RTT样本|
$$
这里 β 是个小于 1 的系数,它的推荐值是 1/4。
6.3 选择确认SACK
若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经正确到达接收方的数据?用选择确认SACK。
但 SACK 文档并没有指明发送方应当怎样响应 SACK。因此大多数的实现还是重传所有未被确认的数据块。
7.TCP 的流量控制
7.1 利用滑动窗口实现流量控制
流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收。TCP 窗口单位是字节,不是报文段。
7.2 TCP 的传输效率
7.2.1 TCP 的发送时机
- TCP 维持一个变量,它等于最大报文段长度 MSS。只要达到 MSS,就封装成一个 TCP 报文段发出去。
- 由发送方的应用进程指明要求发送的报文段,TCP 再推送。
- 有发送方的一个计时器期限到了,就把当前缓存发出去。
但如何控制 TCP 发送报文段的时机仍然是一个较为复杂的问题,在 TCP 的实现中 广泛使用 Nagle 算法。
7.2.1 糊涂窗口综合征
糊涂窗口综合征(silly window syndrome)[RFC 813],有时也会使 TCP 的性能变坏。设想一种情况:TCP 接收方的缓存已满,而交互式的应用进程一次只从接收缓存中读取 1 个字节(这样就使接收缓存空间仅腾出 1 个字节),然后向发送方发送确认,并把窗口设置为 1 个字节(但发送的数据报是40字节长)。接着,发送方又发来 1 个字节的数据(请注意,发送方发送的 IP 数据报是 41字节长)。接收方发回确认,仍然将窗口设置为 1 个字节。这样进行下去,使网络的效率很低。
解决方法:
- 让接收方等待一段时间,使得或者接收缓存已有足够空间容纳一个最长的报文段。
- 或等到接收缓存已有一半空闲的空间。
8.TCP 的拥塞控制
8.1 拥塞控制的一般原理
拥塞控制是一个全局性过程,涉及到所有主机、所有的路由器,以及与降低网路传输性能有关的所有因素。
$$
\Sigma 对资源的需求 > 可用资源
$$
从控制理论的角度,可以分为开环控制和闭环控制两种方法。
- 开环控制:就是在设计网络时事先将有关发生拥塞的因素考虑周到,力求网络在工作时不产生拥塞。但一旦整个系统运行起来,就不再中途进行改正了。
- 闭环控制:是基于反馈环路的概念,主要有以下几种措施:
- 监测网络系统以便检测到拥塞在何时、何处发生。
- 把拥塞发生的信息传送到可采取行动的地方。
- 调整网络系统的运行以解决出现的问题。
8.2 TCP 的拥塞控制方法
TCP 进行拥塞控制的算法有四种:
- 慢开始(slow-start)
- 拥塞避免(congestionavoidance)
- 快重传(fast retransmit)
- 快恢复(fast recovery)
8.2.1 慢开始和拥塞避免
基于窗口的拥塞控制。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。
💡 判断网络拥塞的依据就是出现了超时。
慢开始:当主机开始发送数据时,由于并不清楚网络的负荷情况,所以如果立即把大量数据字节注入到网络,那么就有可能引起网络发生拥塞。较好的方法是先探测一下,即由小到大逐渐增大发送窗口。
8.2 主动队列管理 AQM
💡 TCP 的全局同步:导致以连串分组丢失,发送又发,进入 TCP 拥塞控制满开始状态。
为了避免发生网络中的全局同步现象,在 1998 年提出了主动队列管理 AQM (Active Queue Management)。所谓“主动”就是不要等到路由器的队列长度已经达到最大值时才不得不丢弃后面到达的分组。这样就太被动了。应当在队列长度达到某个值得警惕的数值时(即当网络拥塞有了某些拥塞征兆时),就主动丢弃到达的分组。这样就提醒了发送方放慢发送的速率,因而有可能使网络拥塞的程度减轻,甚至不出现网络拥塞。
AQM 可以有不同实现方法,其中曾流行多年的就是随机早期检测 RED(Random Early Detection):
- 若平均队列长度小于最小门限,则把新到达的分组放入队列进行排队。
- 若平均队列长度超过最大门限,则把新到达的分组丢弃。
- 若平均队列长度在最小门限和最大门限之间,则按照某一丢弃概率 p 把新到达的分组丢弃(这就体现了丢弃分组的随机性)。
9.TCP 的运输连接管理
TCP 是面向连接的协议。运输连接是用来传送 TCP 报文的。TCP 运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。因此,运输连接就有三个阶段,即:连接建立、数据传送和连接释放。
9.1 TCP 的连接建立(三报文握手)
TCP 建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个 TCP 报文段。
- 一开始,B 的 TCP 服务器进程先创建传输控制块 TCB,准备接受客户进程的连接请求。然后服务器进程就处于 LISTEN(收听)状态,等待客户的连接请求。
- A 的 TCP 客户进程也是首先创建传输控制模块 TCB。然后,在打算建立 TCP 连接时,向 B 发出连接请求报文段,这时首部中的同步位 SYN = 1,同时选择一个初始序号 seq = x。TCP 规定,SYN 报文段(即SYN= 1的报文段)不能携带数据,但要消耗掉一个序号。这时,TCP 客户进程进入 SYN-SENT(同步已发送)状态。
- B 收到连接请求报文段后,如同意建立连接,则向 A 发送确认。在确认报文段中应把 SYN 位和 ACK 位都置 1,确认号是 ack = x +1,同时也为自己选择一个初始序号 seq =y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。这时 TCP 服务器进程进入 SYN-RCVD(同步收到)状态。
- TCP 客户进程收到 B 的确认后,还要向 B 给出确认。确认报文段的 ACK 置 1,确认号 ack =y + 1,而自己的序号 seq=x +1。TCP 的标准规定,ACK 报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是 seq = x +1。这时,TCP 连接已经建立,A 进入 ESTABLISHED(已建立连接)状态。
- 当 B 收到 A 的确认后,也进入 ESTABLISHED 状态。
💡 为什么 A 最后还要发送一次确认呢?这主要是为了防止已失效的连接请求报文段突然又传送到了 B,因而产生错误。
现假定出现一种异常情况,即 A 发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达 B。本来这是一个早己失效的报文段。但 B 收到此失效的连接请求报文段后,就误认为是 A 又发出一次新的连接请求。于是就向 A 发出确认报文段,同意建立连接。假定不采用报文握手,那么只要 B 发出确认,新的连接就建立了。
9.2 TCP 的连接释放(四报文握手)
数据传输结束后,通信的双方都可释放连接。
- A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的终止控制位 FIN 置 1,其序号 seq= u,它等于前面己传送过的数据的最后一个字节的序号加 1。这时 A 进入 FIN-WAIT-1(终止等待1)状态,等待 B 的确认。
- B 收到连接释放报文段后即发出确认,确认号是 ack = u +1,而这个报文段自己的序号是 v,等于 B 前面已传送过的数据的最后一个字节的序号加 1。然后 B 就进入 CLOSE-WAIT(关闭等待)状态。TCP 服务器进程这时应通知高层应用进程,因而从 A 到 B 这个方向的连接就释放了,这时的TCP连接处于半关闭(half-close)状态,即 A 已经没有数据要发送了,但 B 若发送数据,A 仍要接收。也就是说,从 B 到 A 这个方向的连接并未关闭,这个状态可能会持续一段时间。
- A 收到来自 B 的确认后,就进入 FIN-WAIT-2(终止等待2)状态,等待 B 发出的连接释放报文段。
- 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。这时 B 发出的接释放报文段必须使 FIN = 1,进入 LAST-ACK(最后认)状态,等待A的确认。
- A 在收到 B 的连接释放报文段后,必须对此发出确认。在确认报文段中把 ACK置 1,确认号 ack = w +1,而自己的序号是 seq =u +1(根据TCP标准,前面发送过的FIN 报文段要消耗一个序号),然后进入到 TIME-WAIT(时间等待)状态。
- A 必须经过时间等待计时器(TIME-WAIT timer)设置的时间 2MSL 后,A 才进入到 CLOSED 状态。
💡 MSL 叫做最长报文段寿命(Maximum Segment Lifetime),RFC 793 建议为 2 分钟。
为什么 A 在 TIME-WAIT 状态必须等待 2MSL 的时间呢?
- 为了保证 A 发送的最后一个 ACK 报文段能够到达 B。
- 防止“已失效的连接请求报文段”出现在本连接中。
9.2.1 TCP 的连接保活计时器释放
TCP 还设有一个保活计时器(keepalive timer):若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔 75 秒钟发送一次。若一连发送 10 个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,就关闭这个连接。