【计算机网络】TCP协议深度解析:可靠性保障与性能优化机制全揭秘
文章目录
- 前言
- 1. TCP 协议简介
- 面向字节流的粘包问题
- 1.1 理解 TCP
- 2. TCP 协议报文格式
- ACK 确认应答机制
- 捎带应答机制
- 超时重传机制
- 流量控制
- 滑动窗口算法
- 快重传
- 3. TCP 协议的相关机制
- 延迟应答(补充Nagle)
- 拥塞控制(慢启动)
- 4. TCP 连接管理机制
- 总结
前言
本文章将会和大家一起了解 TCP/IP 协议栈中的传输层中的 TCP 协议。
1. TCP 协议简介
-
TCP:
TCP(Transmission Control Protocol,控制传输协议)这是一个有连接,可靠的传输层协议。
TCP 协议的主要特点:
-
面向连接:利用 TCP 协议的双方在进行通信之前,必须建立通信信道,每一个双端都需要维护各自的连接,不仅仅需要管理建立连接,还需要管理断开连接。这样的一个机制通过:三次握手、四次挥手。
-
可靠:TCP 协议通过各种机制来确保数据不丢失、不重复、不乱序。例如:ACK 确认应答、超时重传、序列号……
-
数据流:TCP 协议并不会关心来自应用层的数据的边界,TCP 协议自己将数据看出一连串无结构的字节流,由 TCP 协议自己来决定上层的数据发送多数什么时候发送。
-
面向字节流的粘包问题
-
如下图:

正如我们上面给出的示例,用户的多个应用层请求可能会在 TCP 维护的缓冲区中积累,由 TCP 自己决定什么时候将内容发送出去,而 TCP 不会关注这些请求的边界,而是根据自己的规则发送数据。这就导致了对端可能受到的数据不是一个完整的请求/多个请求(0.9个请求/4.1个请求)。
-
这就诞生了一个问题:当 TCP 发送的数据中含有多个应用层请求,我们应该如何区别呢? (数据粘包问题)
当我们在应用层使用
read这样的调用的时候,会将 TCP 维护的缓冲区的数据都拿出来。此时,我们应用层应该做好数据解析的准备。所以我们有如下的方法:主要的行为:明确报文和报文之间的边界。
- 定长报文:规定每一个数据的大小只能是多数,所有解析数据的时候,就提取多大的数据。
- 使用特殊的字符:比如说使用
\r\n、%……字符。 - 使用自描述字段 + 定长报头。
- 使用自描述字段 + 特殊字符:经典的 http 的实现,在报头中有一个字段 Content-Lenth 描述了请求正文的长度,同时在报头和请求正文之间有一个特殊的字符:
\r\n来明确规定边界。
1.1 理解 TCP
-
我们在认识 TCP 协议之前,先来理解一下什么是控制传输?
如下图:

TCP 协议在通信的双方都维护了两个缓冲区,这两个缓冲区分别是一个是发送缓冲区/接受缓冲区。
当上层应用层在使用 write 这样的函数的时候,不会马上就数据写入到对方的接受缓冲区中,而是积累到自己的内核维护的发送缓冲区中。
-
如何理解传输管理,结论:
-
数据什么时候发送?
-
数据在发送的时候,发送多少?
-
数据发送过去之后出错了怎么办?
-
……
这些有关于数据发送/接受管理的信息都是由 TCP 协议来进行管理。
-
-
2. TCP 协议报文格式
小编在介绍 TCP 协议报文格式的时候,会涉及介绍由这些字段引起的一些机制。
-
如下图:

-
我们需要解决的两个问题:
-
Q:TCP 协议中的报头和有效载荷是如何分离的?
A:TCP 协议采用固定长度的报头 + 自描述字段(描述整体长度),这个固定长度的报头长度为20字节。再根据读取的内容的4位头部长度就能读取到整个报头长度了。
-
Q:有效载荷是如何交付给上层的?
A:在 TCP 报文的报头中有一个字段 “16位的目标端口号”。这个字段描述了应该交付给上层处于应用层的哪一个进程。
-
下面我们就来详细介绍一下这些字段:
-
源端口号和目的端口:
为了表示发送应用程序和接受应用程序。这个作用都是为了让内核识别应该把有效载荷交付给上层的应用程序。
-
4位首部长度:
这是用于指示 TCP 头部的长度(以32位字为单位)因为报头信息中有一个“选项”,所以需要这个字段来定位数据部分的起始位置。这个字段占四个字节范围是[0, 15],但是实际范围是 [5, 15]。其中最小值5表示20字节,最大值15表示60字节。
-
16位校验和:
用于检错。检查数据包在传输过程中是否发生错误。计算的内容:不仅仅计算 TCP 数据部分,同时还会引入一个“伪头部”(包括源IP、目的IP、协议号(协议号为6))。主要在于接受方,和发送方进行同样的数据计算,如果校验和相同,那么就证明数据是有效的;否则,证明数据是无效的。
-
16位紧急指针:
当控制标记位的 URG=1 的时候生效。它指出了本报文段中紧急数据的末尾在数据流中的位置(相对于当前序列号的偏移量)
-
选项:
这个字段用于是西安一些高级功能:
-
MSS(Maximum Segment Size):在进行握手/进行通信的时候告诉对方,本方能够接受的最大报文长度。(管理传输)(结合滑动窗口)
-
SACK(Selective Acknowledge):选择性确认,提高重传效率。
-
窗口缩放因子:用于支持更大的窗口。
-
-
序列号和确认序列号:
-
序列号:这是用来表示当前的报文信息的编号。表示本次发送的报文数据的第一个字节在数据流中的字节序号。
其中有两个核心作用:
-
保证接受数据是有序的。我们可以根据序列号进行排序,序列号较小的数据是考前的数据,即使由于网络延迟等因素,我们 TCP 的接受缓冲区仍然可以通过序列号来维护数据的有序性。
-
对数据去重。由于我们的数据由于网络延迟迟迟没有让接收方接受到数据,那么发送方也没有受到 ACK 确认。所以进行超时重传,但是当我们超时重传之后的不久就受到了来自对端的响应,这个时候就会有两份数据到达对方。对方就可以根据序列号进行去重。
-
-
确认序列号:期望接受的序列号。表示接收方期望收到下一个报文的列列好。同时,它也隐式确定了在此序列号之前的数据已经全部收到。
注意:建立连接时(在三次握手中),双方会交换各自的初始序列号。这个号是随机生成的,它本身并不代表任何数据字节。它只是为后续的数据传输建立一个起始基准点。
例子:假设客户端发送的第一个数据报文包含了 100 个字节的数据。如果它使用的初始序列号是 X,那么:这个报文的序列号字段值就是 X。这个报文所携带的数据,其第一个字节的序号是 X,第二个是 X+1,…,最后一个是 X+99。客户端发送的下一个报文的序列号将是 X + 100,因为这将是下一个数据块的第一个字节的序号。服务器收到了客户端发送的序列号为 X,包含 100 字节数据的报文。服务器会回复一个确认报文(ACK标志),其中的确认号字段设置为 X + 100。这个 X + 100 的含义是:“我已经收到了直到 X+99 号字节的所有数据,请接下来从 X+100 号字节开始发送。”
注意:TCP 协议栈会自行计算数据流的长度。
-
-
6位控制标志位:
6位的控制标志位是一个用位图来管理的:0表示不含有该属性、1表示含有该属性。
-
URG:紧急指针有效。这个标志位的作用就是标记当前的报文中的16位紧急指针是生效的。
-
ACK:16位确认序号有效。这个标志位的作用就是告诉对方,在本确认序列号之前的内容我已经收到了。
-
PSH:推送标志。提示接受端应该立即将数据交给应用层,而不是等接受缓冲区满。
-
RST:强制终止连接。TCP 保证建立连接之后的数据可靠性,但是不保证连接一定成功(不能保证一些异常情形下连接仍然建立)。这个字段表示当前连接出现错误,需要强制断开连接。
-
SYN:同步标志。在建立连接(进行三次握手)的时候进行使用,用来同步序列号。
-
FIN:结束标志。用来关闭连接(进行四次挥手),表示本方没有数据进行发送了,需要断开连接。
-
基于上面的 ACK 机制,实现了很多的机制:
- ACK 确认应答机制
- 捎带应答机制
- 超时重传机制
下面我们逐一介绍
ACK 确认应答机制
在上面介绍 ACK 和 确认序列号的时候我们已经涉及了这样的一个机制,下面小编再来重新介绍一下。
在我们日常聊天的过程中,假设我们给一个朋友发送了很多信息,但是我们的朋友只回复了一条信息。那么我们能够确认的是:我的最后一条发送的信息一定是被朋友接收到了。这样的场景是互相的。
在两个人互相发送信息的场景下(一发一答),我们能够保证有回应的信息是被对方接受到了;但是我们最后发送的信息(没有回应的最新信息)是无法保证被对方看到的。
-
结论:我们无法保证最新的一条发送信息是一定能被对方接受到的。但是,我们能够通过对方的响应来确认我们之前发送的信息是被接受到的!

所以,我们能够通过对方的响应来说明是否我们之前的数据被收到了。 -
这样的机制基于两个属性:
-
确认序列号
-
ACK 标志位。
-
-
如下图:

假设起始序列号是1。当客户端发送了一个 TCP 报文之后,发送的报文序列号就是1。当对方收到报文之后,协议栈会自己进行数据解析,准备发送一个 ACK 响应。通过计算,当前的数据流中有 1000 个字节的数据,那么服务器就在字节的 TCP 报头中添加一个 ACK 标志位和 1 + 1000 的确认序号。-
当前的序列号1001之前的数据我已经收到了。
-
我希望下次收到的数据是序列号为1001开始的。
这就是 ACK 确认应答机制,能够保证局部上的数据安全性。
-
捎带应答机制
但是上述的简单的一次发送和一次ACK响应的效率十分低下。
考虑上图:C发送了 TCP 报文了,S响应了一个纯 ACK 确认报文,同时S又想发送数据怎么办?
-
如果我们仅仅考虑到上图的发送的话,我们会将这一次 ACK 和 发送数据分为两次发送
这样的方式:效率较低、而且数据风险不安全的更大。
我们可以考虑将 数据 和 ACK 在同一次报文中体现。即同一个 TCP 报文中,我们既可以发送我们想要发送的数据,也可以告知对方下一次期望的收到序列号。
-
如下图:

以这样的方式,我们就可以两次发送合并成为一次了。
超时重传机制
-
如下图:

因为网络传输是需要时间的。所以一个报文发送到接受到答应的之间是有时间间隔的。
考虑下面的问题:如果在数据发送的过程中数据丢失了呢?如果在答应的时候,答应丢失了呢?
-
问题的根源在于:发送端无法主动判断对方是否已经接受到了数据。
-
解决方案:
-
超时重传机制:我们可以规定一个时间段。如果在这个时间段内,发送方没有接受到来自对端的响应,我们就认为数据丢失了。那么发送端就是重新发送之前发送的数据。
如下图:

-
-
那么这个特定的时间段,什么时候比较合适呢?
如果这个时间段设置不合理会面临以下问题:
-
如果超时时间设置太长:会影响整体重传效率。
-
如果超时时间设置太短:有可能会发送重复的数据。
最理想的情况下,我们需要找到一个最小的时间,保证“确认应答一定能在这个时间内返回”。但是这个时间是随着网络环境是由差异的。所以,TCP 为了保证无论在任何环境下都有比较高的性能,因此会动态计算这个超时时间。
Linux中(BSDUnix和Windows也是如此),超时以 500ms 为一个单位进行控制,每次判断超时重发的超时时间都是 500ms 的整数倍。
如果在一次重传之后仍然得不到应答,等待2 * 500ms后再进行重传。
如果在一次重载之后仍然得不到答应,等待4 * 500ms进行重传,逐次重传,以指数形式重传。
统计到一定的严重传播次数,TCP 认为网络或对端主机出现异常,强制关闭连接。 -
- 16位窗口大小:这是实现流量控制的关键。表示从确认号开始,接受方当前愿意收到的字节数量。这是一个动态变化的、接收方告知的 “接受窗口大小”。如果这个字段为0,表示发送方停止发送。
流量控制
使用 TCP 协议通信的双方都是有接受缓冲区的。这个缓冲区是有大小限制的。所以,我们不能让发送的一方无限制的发送数据,如果上层应用层没有及时读取接受缓冲区中的数据,就会导致严重的问题。
- 16位窗口大小:就是告知对方接受缓冲区(接受窗口)的接受能力。然后配合 “滑动窗口” 算法来进行调整发送的力度。
我们来看下面几个问题:
-
Q:当接受方(主机B)的能力达到上限的时候,窗口大小就会被设置成为0。此时发送方(主机A)也就不会发送数据了,那么它们又是如何开始新的发送数据的呢?
A:两个方面
-
如果是互相通信的场景,那么主机B也会向主机A发送数据,在发送的 TCP 报文中就会携带窗口信息。例如:ACK 确认、捎带应答……发送类似的消息都会携带当前窗口大小。
-
如果是单方面的场景,那么主机A会主动向主机B发送一个“窗口探测”,目的就是询问主机B的缓冲区是否准备好了。如果主机B的缓冲区准备好了,就会回复一个 “窗口更新通知”。
这样的方式除非通信的双方都出现了问题,那么这样的方式就不会因为一端的故障就整个连接的故障。TCP 连接的存活不依赖于某一方的绝对健康,而是依赖于一个双向的反馈机制 。通信的一端出了问题,连接本身有尝试自我修复和等待的机制,不会立刻“猝死”。

-
-
Q:那么第一次发送数据的时候如何保证数据的合理性呢?
A:在真正进行数据通信之前,通信双方需要进行 “三次握手”,在三次握手的过程中就可以协商接受能力。
-
Q:流量控制是为了可靠性还是效率?
A:流量控制主要是为了可靠性,以效率为辅助。主要就是为了维护接受缓冲区的接受能力。
滑动窗口算法
滑动窗口算法是实现流量控制的一个手段
滑动窗口算法的根本目的是在保证可靠性的前提下,极大地提高性能。
-
认识滑动窗口:
在 TCP 协议中,数据是通过序列号来维护数据的顺序关系的。那么通过序列号,我们可以将接受缓冲区的数据看作是一个线性结构。
前置:
-
TCP 具有重新发送数据的能力,所以对于已经发送过的数据但是没有接收到应答的数据,TCP 有能力能够保存。同时,发送方可能发送了多个数据都没有得到合理的应答。
结论:TCP 有能力维护多个没有收到应答的数据。
那么而 TCP 的发送数据都被维护在发送缓冲区中,所以我们就可以将发送缓冲区根据线性进行区域的划分:

主要就有三部分组成:
-
已经响应的数据/空数据(统一为可覆盖的数据)
-
已发送但未答应的数据
-
未发送的数据
滑动窗口的范围:覆盖的是发送缓冲区中 已发送但未确认 + 未发送但可立即发送 这两个部分组成的连续线性区域。
注意:小编这里在强调 “发送缓冲区在逻辑上是一个连续结构”,实际结构可能不是一个简单的物理连续结构(数组)。例如:Linux 内核的发送缓冲区就是以链表的形式管理的。但是我们仍然能够通过 序列号 来实现逻辑上的连续结构。
-
-
滑动窗口相关认识:

-
滑动窗口是什么?
是 TCP 维护的发送缓冲区的一个线性区域。
-
滑动窗口的范围是什么?
滑动窗口内部是分段的,因为它需要控制每次发送的数据量的大小。每次发送的数据是有限制的:由多种因素决定:MSS、对方的接受能力、网络……
-
如何理解滑动窗口/如何理解“滑动”?
滑动窗口就是根据序列号的两个指针维护的一段区域。当发送方收到接收方新的 ACK 应答时,会发生两件事:左边界向右移动:ACK 确认了窗口内最左边的一部分数据,于是窗口的左边界向右收缩;右边界可能向右移动:如果 ACK 报文里携带了新的、更大的窗口通告,那么窗口的右边界也可能会向右扩展。这个一收一扩(或只收不扩)的过程,就像窗口在向右“滑动”。
-
滑动窗口是如何解决 ACK 答应丢失/数据包丢失的场景?
结合确认序列号。
-
场景(ACK答应丢失):如果发送方发送了多个数据,其中的某个 ACK 答应出现丢包的情况,但是由于接受方已经合理的收到了数据,那么接受方后续的响应中会将确认需要更新到期望的序号。
例如:假设由序列号1-100 101-200 201-300 301-400 发送方发送这些数据成功了,但是响应方的 ACK 响应 101-200 的响应丢失了,但是当发送方接受到来自 201-300 的响应的时候,发送方就会知道:101-200 的数据即使没有 ACK 响应也能说明接受方已经收到了。301-400 同理。
-
场景(数据包丢失):如果发送方发送了多个数据,其中某个数据包发送了丢失,但是由于接收方没有接收到按序列号的数据,那么接收方所响应的确认需要一直都会维持在没有收到的序列号。
例如:假设由序列号1-100 101-200 201-300 301-400,发送方发送了这些数据成功除了101-200。那么接收方只会收到来自1-100 201-300 301-400 的数据(接受缓冲区会维护数据的有序性),当接受方返回 ACK 的时候,发现自己并没有 101-200 的数据,于是响应的时候确认序号都会是 101,即使收到的数据已经到了序列号400。当发送方正确的发送了 101-200 的数据的时候,接收方会自动检测数据101开始的序列数据是否已经完成,响应的时候就会将确认序号更新到401。
上面的场景中,我们第一次正常发送了三个数据包,但是三次的响应中的确认序列号都是 101。像这样如果接受到多次相同的确认序号,发送方将重新发送的机制被称为“快重传”。发送方直接发送丢失的101-200的数据包,不需要等待超时时间。
结论:只要发送方接受到了来自接受方的确认序号,就可以更新滑动窗口的左边界。
-
-
快重传
上面的案例也说明了快重传的场景。
-
快重传:当收到3个或3个以上重复的ACK时,就立刻重传对方所要求的数据段,而不必等待超时。
-
为什么需要快重传?
在标准的 TCP 重传机制中,主要依赖一个叫做 重传超时的计时器。如果发送方在一个特定的时间(RTO)内没有收到某个数据段的确认,它就认为这个数据段丢失了,然后进行重传。
然而,RTO 的值通常是根据网络往返时间动态计算的,并且最小值通常被设置为200ms。这意味着,即使数据包真的丢失了,发送方也要傻等至少200ms才会开始重传。对于现代高速网络来说,这个等待时间太长了,会导致网络吞吐量急剧下降,用户体验变差(比如视频卡顿、游戏延迟)。
3. TCP 协议的相关机制
上面我们在介绍 TCP 协议报文的时候就涉及了大量的机制了,下面我们对一些机制进行补充
延迟应答(补充Nagle)
-
一个事实:
发送方一次发送的更多数据,网络吞吐量也就更高,效率也就更高。那么我们可以考虑:
- 接受方的窗口大小尽可能大 — 延迟应答。提高网络吞吐量,充分利用带宽。
-
延迟应答
TCP通过滑动窗口协议进行流量控制。接收方会告诉发送方自己的接收窗口大小,即自己还能接收多少字节的数据。如果接收方每收到一个数据包就立即回复一个ACK,并通告一个新的(可能很小的)窗口,那么发送方就会根据这个很小的窗口来发送数据,导致数据流变成一小段一小段的,无法充分利用网络的带宽。
-
核心:接收方收到数据时,不要立即回复ACK,而是稍微等待一段时间。
这段时间内:可以等待上层读取数据/等待上层写数据(触发捎带应答)。
-
工作流程:
延迟应答并非无限期延迟,它有严格的规则来避免造成发送方不必要的超时重传:
-
数量限制:通常每两个连续的数据包,至少需要立即 ACK 一个。例如,Linux的实现中,默认最多允许连续两个包被延迟应答。
-
时间限制:有一个最大延迟时间,通常不超过40 ms 或 200ms(具体实现不同)。那么如果定时器超时,接收方必须立即发送ACK。
-
-
-
Nagle 算法
想象一个场景:用户通过 Telnet 或 SSH 连接到服务器,每次击键都会发送一个字符。在TCP中,这个字符可能只有1字节的数据。然而,封装这个数据的 TCP 报文段和 IP 数据报却有至少40字节(20字节TCP头 + 20字节IP头)的头部开销。这就造成了极大的网络效率浪费,大量带宽被头部信息占用,有效数据载荷极低。这种情况被称为“愚蠢窗口综合征”的一种表现。
-
核心:在任意时刻,最多只能有一个未被确认的小数据包(小于MSS)在传输中。
-
工作流程:
-
如果发送的数据量达到或超过MSS,立即发送。
-
如果数据量小于MSS,且之前所有发出的数据包都已被确认(ACK),则立即发送这个小的数据包。
如果数据量小于MSS,且之前还有未被确认的数据包,那么发送方会等待。它有两种结束等待的方式:
-
等待ACK到达:一旦收到之前数据的ACK,它就会把缓冲区里积累的数据一并发送出去。
-
等待数据积累:在等待期间,如果应用程序又写入了新的数据,使得缓冲区中的数据总量达到了MSS,则立即发送。
-
-
-
-
Nagle算法 是一种相对粗犷的、以牺牲延迟为代价来换取网络效率的机制。它在当今高速网络和低延迟需求面前已经过时,是高性能网络编程中通常需要禁用的选项。注意:Nagle算法的效率价值在下降。Nagle 在现代网络中对"整体效率"的贡献往往是负面的。
-
两者结合使用时,可能会产生不良的性能副作用。例如,发送方因 Nagle 算法而延迟发送,接收方因延迟应答而延迟回复ACK,两者互相等待,导致延迟叠加。因此,在需要低延迟的场景,通常建议同时禁用 Nagle 算法并启用快速 ACK。
小结:
- 延迟应答机制 是一种相对精巧的、以微小延迟代价换取巨大吞吐量收益的机制。
拥塞控制(慢启动)
想象一下高速公路在高峰期。如果入口匝道不加限制地放行所有车辆,最终会导致主路车辆密度过大,车速急剧下降,甚至引发全线瘫痪(即拥塞崩溃)。计算机网络也是如此。
我们不同的主机进行通信的时候是通过网络来进行通信的。而网络作为共享资源,无时无刻有无数的 TCP 连接都在共享网络资源。这就导致:两台主机之间的通信出了问题,可能是网络问题。
-
拥塞控制: 解决的是发送方发得太快,导致网络(路由器、交换机)来不及处理的问题。它是一个端到网络的问题。
TCP 通过维护一个 拥塞窗口(cwnd) 来解决这个问题。发送方的实际有效窗口是 min(cwnd, rwnd)。(通知窗口,rwnd)
- 通知窗口大小:考虑的是对端能够接受数据的能力。
- 拥塞窗口大小:考虑到是网络的接受能力。
-
拥塞控制主要通过:慢启动、拥塞避免、快重传、快恢复来防止网络拥塞
这里我们主要介绍慢启动
-
慢启动:先向网络中发送少量数据,试探一下网络的接受能力,再决定按照多大的窗口进行发送数据。

呈现指数级别增长(考虑对端的接受能力强)。 -
过程:
-
初始时,拥塞窗口通常设置为 1 个 MSS(最大报文段长度)。
-
发送方每收到一个 ACK,就将拥塞窗口增加 1 个 MSS。
这意味着,每经过一个数据的往返时间(RTT),拥塞窗口大小就会翻倍(指数增长)。慢启动含义:只是启动的时候数据传输很慢。
-
-
结束条件(出口):
-
超时: 发生了数据包丢失(超时重传),TCP 认为网络拥塞严重。将慢启动阈值(ssthress)设置为 cwnd/ 2 。将 cwnd 重置为 1,重新开始慢启动。
-
达到慢启动阈值:当 cwnd 增长到预设的慢启动阈值时,转为拥塞避免阶段。
-
快速重传: 收到 3 个重复的 ACK(说明有包丢了,但后续的包还能到达),则进入快速恢复阶段。
-

-
当 TCP 开始启动的时候,慢启动阈值等于窗口最大值
-
在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回 1;少量的丢包,我们仅仅是触发超时重传;大量的丢包, 我们就认为网络拥塞;当 TCP 通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降;
-
拥塞控制:归根结底是 TCP 协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。
4. TCP 连接管理机制
小编已经整理成一文了:TCP链接管理。
-
也可以参考下图:

总结
TCP 协议实现了很多的策略:
-
可靠性方面:
- 校验和
- 序列号(去重、顺序,配合)
- 确认应答(需要配合确认序号)
- 超时重传
- 链接管理(三次握手和四次挥手也是实现可靠性的策略)
- 流量控制
- 拥塞控制
-
性能方面:
- 捎带应答
- 滑动窗口(一次可以发送多个数据包)
- 延迟应答
- 快速重传
-
状态检测机制:
- 超时重传定时器
- 定时保活计时器
- TIME_WAIT计时器
- ……
完。
更多推荐


所有评论(0)