传输层提供的服务
传输层概述
两台主机的两个应用通过 IP + 端口号(套接字) 实现通信
套接字分为: TCP 套接字和 UDP 套接字
注意
两台主机的端口号是相互独立的
TCP 、 UDP 的端口号也是相互独立的
当两个进程之间需要进行通信时,需要指明:
使用哪种传输层协议
本进程绑定的端口号
对方 IP 地址和端口号
熟知端口号
0~1023 为熟知端口号,开发的时候一般不使用
其他端口号在实际开发时没有特别严格的限制,只要在本机没有被使用的端口号都可以使用
端口号分类只是一种“建议标准”,而非“强制标准”
常见熟知端口号
| 应用程序 | FTP | TELNET | SMTP | DNS | TFTP | HTTP | SNMP |
|---|---|---|---|---|---|---|---|
| 端口号 | 21 | 23 | 25 | 53 | 69 | 80 | 161 |
有连接和无连接
有连接:在传输数据前先打招呼,先确认对方已经准备好接收数据。传输结束时也要告知对方已结束
无连接:不打招呼,直接把数据传给对方
可靠传输和不可靠传输
可靠传输:接收方使用“确认机制”让发送方知道哪些数据已经被正确接收
不可靠的:接收方无论收没收到数据、数据是否正确,都不给发送方反馈
UDP 协议
UDP 数据报
传输层收到应用层的数据后会在其首部添加一个 8 B 大小的 UDP 首部
UDP 数据报有以下特点
UDP 首部很小只占 8 B
UDP 每次传输一个完整的报文,不支持报文自动拆分、重装
UDP 是无连接的、不可靠的(可靠性可以交给应用层处理),也不支持拥塞控制
UDP 支持一对一(封装成单播 IP 数据报)、一对多传输(封装成广播 / 多播 IP 数据报)
注意
- 由于 UDP 不支持报文拆分和重装,因此应用层的报文长度不能超过 UDP 协议上限
UDP 数据报中,首部固定占 8 B
首部各字段及其作用:
| 字段名 | 作用 |
|---|---|
| 源端口号 | 发送进程的端口号(如果不需要对方回复可以全设置为 0 ) |
| 目的端口号 | 接收进程的端口号(必填) |
| UDP 长度 | 包含首部,以“字节”为单位 |
| UDP 检验和 | 由发送方的传输计算并填入校验和,接收方的传输层检测是否有差错(如果无需校验,可以填入全 0 ) |
数据部分为一个完整的应用层报文
UDP 数据报理论最大长度为 65535 B ( 64 Kb )这是由 IP 数据报数据部分长度限制( IP 数据报数据部分最长为 65535 B )所限制的
UDP 检验
对于发送方,会在交付给网络层之前进行检验和计算,并将结果填入 UDP 首部的检验和字段中,具体步骤如下
传输层 UDP 协议在计算检验和之前,先添加一个伪首部
把伪首部、首部、数据部分以 16 bit 为一组,进行二进制加法(最高位产生的进位需要回卷)
将最终的加法结果逐位取反,就得到 16 bit 的检验和,将其填入 UDP 首部
去掉伪首部,并将 UDP 数据报交给网络层,封装成 IP 数据报
对于接收方收到数据后也会有相似的操作
网络层向传输层递交 UDP 数据报
传输层在 UDP 数据报之前,添加伪首部
吧伪首部、 UDP 首部、数据部分以 16 bit 为一组,进行二进制加法(最高位的进位需要回卷)
如果加法结果全为 1 ,说明没有比特错误,于是接收该 UDP 数据报,并根据目的端口号,向应用层递交报文;如果加法结果不全为 1 ,说明有差错,于是丢弃该 UDP 数据报
- 二进制计算过程
假设有 48 bit 数据为:
计算过程为:
得到检验和为:1110 0000 1000 0011
注意
对于伪首部中的字段
| 字段名 | 含义 |
|---|---|
| 源 IP 地址 | 发送方的 IP 地址 |
| 目的 IP 地址 | 接收方的 IP 地址 |
| 全零 | 占 1 B,全 0 ,用于填充 |
| 协议 | 传输层协议( UDP 为 17 ) |
| 数据长度 | UDP 数据报的长度(和首部中的 UDP 长度字段相同) |
对于为什么在过程中需要添加伪首部不需要详细讨论
TCP 协议
TCP 的传输单元称为 TCP 报文段 / TCP 段 因 TCP 协议可对应用层报文进行拆分传输而得名
TCP 传输过程中分为三个步骤,这三个步骤中传输的数据单元均为 TCP 段
建立连接(三次握手)
数据传输
释放连接(四次挥手)
在上图中, 3 次握手对应发送三个 TCP 报文段
握手后建立 TCP 连接可以进行全双工通信
挥手 ① 和挥手 ② 表示进程 A 已经没有需要发送的数据了,两次挥手后单向断开连接
之后只有进程 B 可以向进程 A 发送数据,反之则不行
挥手 ③ 和挥手 ④ 表示进程 B 也没有需要发送的数据了,这两次挥手后关闭进程 B 到进程 A 的连接
最后结束通信
注意
建立一次 TCP 连接可以传输多个应用层报文(可双向)
TCP 是面向字节流的(而 UDP 是面向报文的),无论传输多少应用层报文,在 TCP 看来就是一大串字节流即字节流是无边界的,一个 TCP 报文段可以包含多个应用层报文的分段
挥手结束 TCP 连接时可以由服务器发起第一次挥手也可以由客户端发起
TCP 报文段数据部分的大小受限于 MSS (Max Segment Size),MSS 是 TCP 连接双方协商的最大报文段数据部分大小(有效大小),MSS 的值在 TCP 连接建立时协商,并且 TCP 段不会强制要求数据部分大小一定要填充至 MSS 只需要保证不超过即可
TCP 数据报
TCP 数据报有以下特点:
TCP 首部更大,占 20 B ~ 60 B
TCP 支持报文自动拆分、重装,因此可以传输长报文
TCP 是有连接的、可靠的、支持拥塞控制
TCP 仅支持一对一传输(因为通信双方的传输层必须先建立连接)
TCP 支持报文拆分和重装,所以可以进行长报文的传输
对于 TCP 段的首部字段,不需要记住各字段的顺序和位置,只需要记住每个字段的含义即可
TCP 数据段首部各字段及其含义(标红为重点)
| 字段名 | bit 数 | 含义 | 备注 |
|---|---|---|---|
| 源端口 | 16 bit | 发送进程的端口号 | |
| 目的端口 | 16 bit | 接收进程的端口号 | |
| 序号 | 32 bit | 用于标记数据部分第一个字节在原始字节流中的位置 | 用于接收方重组应用层数据报,起始“序号”是由发送方自己设置的,不一定从 0 开始,通常简写为 seq |
| 确认号 | 32 bit | 用于反馈,表示序号在该确认号(某字节位)之前的所有字节(不包括该字节)都已正确接收 | 通常记为 ack 或 ack_seq |
| 数据偏移 | 4 bit | 数据偏移量,单位为 4 B,指出 TCP 数据段的首部长度 | 取值范围为 0 ~ 15 |
| 保留 | 6 bit | 占 6 bit,全 0 ,目前暂时没有用 | |
| URG | 1 bit | 紧急指针有效位,为 1 时表示该 TCP 数据段为紧急数据,应尽快推送 | 不常考 |
| ACK | 1 bit | 确认号有效位,为 0 时, ack_seq 无效;为 1 时, ack_seq 有效 | 通常记为 ACK ,除握手 ① 之外,其他所有 TCP 段的 ACK 都为 1 |
| PSH | 1 bit | 推送位,为 1 时表示发送方希望接收方尽快回复(用于交互式通信),该种类的报文段会立即触发接收方的应用层处理,不需要等缓冲区满后才移交应用层 | 不常考 |
| RST | 1 bit | 重置连接位,为 1 时表示出现严重差错(如主机崩溃),必须释放连接;同时也可以用于拒绝一个非法报文段(如黑客恶意共计) | 当有一方接收到非法报文段时,会发送一个 RST 为 1 的报文段,示意双方尽快释放连接避免进一步的安全隐患;不常考 |
| SYN | 1 bit | 同步序号位,为 1 时表示这是一个请求连接或者接收连接的报文 | 只有握手 ① 和握手 ② 的 SYN 值为 1 其他都为 0 |
| FIN | 1 bit | 结束位,为 1 时表示发送方没有更多数据要发送了,数据已经发送完毕,要求释放连接 | 只有挥手 ① 和挥手 ③ 的 FIN 值为 1 其他都为 0 |
| 窗口 | 16 bit | 用于流量控制的关键,表示接收窗口的大小。即从本报文段首部中的 ack_seq 算起,接收方还能接收多少数据(以字节为单位),即接收方接收缓冲区的剩余空间大小(这里其实不严谨,如果接收方接收到的数据不连续,则接收窗口从最后一个连续数据的后一字节开始计数到缓冲区结束,哪怕已经正确收到后面的几个字节数据,但只要和前面数据不连续,这些数据也仍在接收窗口内) | 一般简写为 rwnd 或 rcvwnd |
| 校验和 | 16 bit | 用于校验 TCP 数据段首部和数据部分,和 UDP 校验和的计算雷同,也需要添加伪首部再进行计算,只是需要把协议字段的 17 改成 6 (TCP 协议号)、 UDP 长度字段改为 TCP 的长度 | 不常考 |
| 紧急指针 | 16 bit | 紧急数据的专用序号,原理和上面的序号类似,所填的值为当前 TCP 数据段的紧急数据末尾字节的下一字节的偏移量,例如:数据部分长度为 8 字节,紧急数据长度为 4 字节,那么紧急指针就填写 4 (即 0 ~ 3 字节为紧急数据,紧急数据末尾字节的下一字节偏移量为 4 也就是第 4 字节开始都是普通数据,之前的都是紧急数据) | TCP 数据段如同时含有普通数据和紧急数据,紧急数据必须位于普通数据之前,不常考 |
| 选项 | 不定长 | 建立 TCP 连接时,在握手 ① 和握手 ② 中在选项这里协商 MSS ,一般指发送该 TCP 段的来源方的 MSS ,向对方通知自己发送的数据的大小限制 | 一般就考 MSS 在这部分协商 |
| 填充 | 不定长 | 用于将 TCP 段首部填充至 4 B 的整数倍大小 |
TCP 报文段首部没有专门的字段指明 TCP 段的长度为多少(会根据 IP 首部、 TCP 首部的信息算出来)
对于标志位为 1 的 TCP 段可以称为对应的标志名 + 段,例如: SYN = 1 时,对应 TCP 段可称为 SYN 段,对于含多个等于 1 的标志位的 TCP 段可以称所有的标志名 + 段,例如:一个 SYN = 1 且 ACK = 1 的 TCP 段可以称其为 SYN 段,也可以称其为 ACK 段
现实应用中通常 MSS 不会设置得太大,避免 IP 数据报分片
TCP 连接管理
要点:建立连接,数据传输,释放连接过程中, TCP 报文段中 SYN 、 ACK 、 seq 、 ack 等关键字段的变化和区别,以及双方 TCP 状态的变化等
建立连接
握手 ③ 后进入 TCP 双工传输阶段,根据握手 ③ 是否携带数据,服务器发出的第一个 TCP 数据段字段也有所不同
这里假设携带 100 B 数据
| 第一个 TCP 数据段的字段 | 握手 ③ 携带数据 | 握手 ③ 不携带数据 |
|---|---|---|
| SYN | 0 | 0 |
| ACK | 1 | 1 |
| FIN | 0 | 0 |
| seq | 51 | 51 |
| ack | 767 | 667 |
TCP 全过程中,只有握手 ① 和握手 ② 中 SYN 为 1 ,其他都为 0
握手 ① 和握手 ② 不能携带数据(只有 TCP 首部),但是仍要消耗一个序号
握手 ③ 可以携带数据,也可以不携带数据,如果不携带数据,就可以不消耗序号
思考收到某个报文时,双方的状态变化
- 考试要点:
从发出握手 ① 到客户端进程可以发送数据,至少要多久—— 1 RTT
从发出握手 ① 到服务器进程可以发送数据,至少要多久—— 1.5 RTT
题目一般会给出 RTT 的具体值
释放连接
- 考试要点:
在 TCP 全过程中,只有挥手 ① 、挥手 ③ 的 FIN = 1
挥手 ① 、挥手 ③ 即使不携带数据(可以携带数据),也要消耗一个序号
挥手 ② 可以携带数据
挥手 ④ 不可以携带数据
这里也可以是服务器先发起挥手,客户端再发起挥手
- 释放连接阶段耗时分析
客户进程收到挥手 ③ ,立即进入 TIME-WAIT 状态,并启动“ TIME-WAIT 计时器”,倒计时 2 MSL 后才能进入 CLOSE 状态。(如果等待期间重复收到挥手 ③ ,则重置计时器)
MSL ( Max Segment Lifetime ):最大报文段寿命,是 TCP 协议规定的一个固定时间长度,用于指定一个 TCP 报文段在网络中传输的最大时间。
如果服务器收到挥手 ① 时,已经没有待传输的数据,那么可以连续发出挥手 ② 、挥手 ③ ,期间所耗时间极短(处于 CLOSE-WAIT 的时间极短);同样的,客户端也会连续收到挥手 ② 和挥手 ③ ,之间变化两个状态,时间极短(处于 FIN-WAIT-2 的时间极短)
- 考试要点:
从客户端发出挥手 ① ,到客户端进程进入 CLOSE 状态,至少需要多久?—— 1 RTT + 2 MSL
从客户端发出挥手 ① ,到服务器进程进入 CLOSE 状态,至少需要多久?—— 1.5 RTT
一般称握手 ① 和握手 ② 为 SYN 段,挥手 ① 和挥手 ③ 为 FIN 段
TCP 可靠传输和流量控制👍
TCP 会创建一个发送缓冲区和一个接收缓冲区,用于存储数据,这个大小一般由操作系统分配,本质上是一个 char 数组
向对方发送的窗口字段意味自己的接收缓冲区的剩余大小也就是接收窗口的大小,单位为字节( B ),一般窗口会动态调整大小
发送窗口的大小不大于发送缓冲区的大小,也不大于对方接收缓冲区的大小,会根据每次对方传输的 TCP 段中的 rwnd 字段进行调整
TCP 传输过程示例
假设客户端的缓冲区大小为 10 B ,服务器的缓冲区大小为 8 B
根据后两次握手双方交换接收窗口的大小,此时客户端将发送窗口设置为 8 B 对应服务器接收窗口的大小
完成握手后,假设第一次客户端向服务器发送 3 B 数据,也就是发送窗口的前 3 B 数据,服务器接收数据后进行差错控制,并将这 3 B 数据存入接收缓冲区内,假设此时服务器没有开始向客户端发送数据,则返回客户端的 TCP 报文为 ack = 603 ,rwnd = 5 ,表示接收 3 B 数据,600 ~ 602 已正确接收,接收窗口减少 3 B
客户端收到返回的报文后,因为没有收到数据,所以 ack 和 rwnd 不作调整,此时将发送窗口后移 3 B ,并将已发送的数据进行清理,载入新的数据放入缓冲区,此时发送窗口的大小为 5 B ,假设此时客户端连续两次发送 TCP 段,都携带 2 B 数据, seq 字段分别为 603 、 605
服务器连续收到两个 TCP 段,并对这两个 TCP 段进行差错控制,假设没有差错,则将这两个 TCP 段的数据根据其 seq 字段按照顺序(不需要担心数据报到达先后的问题)存入接收缓冲区内,并且会对 ack 进行累加,只返回一份数据报,该数据报字段为 ack = 607 , rwnd = 1
注意
短时间(很短很短的时间, TCP 协议规定的时间最长不超过 0.5 秒)内接收多份 TCP 段,只会返回一份数据报,该数据报的 ack 字段会根据连续收到的数据大小进行累加后得出
接收方如果要捎带数据,则必须收到第一份 TCP 段时,就需要立刻返回 ACK
接收方若收到连续两个长度为 MSS 的报文段,则应该立即返回 ACK (避免数据丢失后,重传代价过大)
正常的 ACK 只有首部,没有数据部分,而捎带数据的 ACK 有数据部分
客户端收到后对缓冲区和发送窗口进行更新,将已发送的数据进行清理,载入新的数据放入缓冲区,发送窗口的大小为 1 B ,此时只能发送 1 B 的数据
服务器收到最后这 1 B 的数据后,此时缓冲区已被填满,接收窗口为 0 ,此时服务器会将这部分数据( 8 B )按顺序交付给应用层,同时情况缓冲区,调整接收窗口为 8 B ,返回报文, ack = 608 , rwnd = 8
客户端收到 ack = 608 的报文后,将发送窗口后移 1 B ,清理已发送的数据,并载入新的数据进入缓冲区,此时发送窗口大小为 0 ,并且根据传回来的报文中 rwnd 字段为 8 说明服务器已经重置接收窗口,于是客户端重新将发送窗口设置为 8 B ,开始下一轮发送
捎带确认
继续上面的例子,此时客户端继续向服务器发送 2 B 数据, seq 字段为 608 ,服务器收到后进行差错控制,并将这 2 B 数据存入接收缓冲区内,此时服务器开始向客户端发送 5 B 的数据,于是将这部分数据载入发送缓冲区,此时服务器发送窗口为 8 B ,向客户端发送的 TCP 段各字段为 seq = 200 , ack = 610 , rwnd = 6
客户端收到该 TCP 段后对数据进行差错控制,没有发现错误后放入接收缓冲区,将接收窗口减小 5 B ,并且根据接收到的 rwnd 字段调整发送窗口,将窗口后移 2 B 并清理数据,载入新数据,向服务器发送 6 B 的数据,此时发送的 TCP 段各字段为: seq = 610 , ack = 205 , rwnd = 5
接收到新 TCP 段,服务器各数据变化如下
接收传输 ③ ,发送传输 ④
发送 0 B 数据,接收 6 B 数据
| 字段 | 内容 |
|---|---|
| seq | 610 |
| ack | 205 |
| rwnd | 5 |
| 数据部分 | 变化 |
|---|---|
| 接收窗口 | 6 -> 0 -> 8 |
| 发送窗口 | 8 -> 5 |
| 字段 | 内容 |
|---|---|
| seq | 205 |
| ack | 616 |
| rwnd | 8 |
- 客户端接收到服务器的 TCP 段,各数据变化如下
接收传输 ④ ,发送传输 ⑤
发送 2 B 数据,接收 0 B 数据
| 字段 | 内容 |
|---|---|
| seq | 205 |
| ack | 616 |
| rwnd | 8 |
| 数据部分 | 变化 |
|---|---|
| 接收窗口 | 5 -> 5 |
| 发送窗口 | 0 -> 8 |
| 字段 | 内容 |
|---|---|
| seq | 616 |
| ack | 205 |
| rwnd | 5 |
- 服务器收到客户端的 TCP 段,各数据变化如下
接收传输 ⑤ ,发送传输 ⑥
发送 0 B 数据,接收 2 B 数据
这里服务器接收窗口的变化为 8 -> 6 -> 8 ,是因为服务器收到 TCP 段后检查无误立刻将报文按序转交应用层(不需要等缓冲区满再提交,可以进行此操作的前提是按序,也就是必须是前 n 个数据都必须完整接收到才能提交;反之假设目前接收窗口内期待的按顺序第一个 TCP 段未收到,此时哪怕已经收齐了后续的所有 TCP 段,也不能提前提交)
| 字段 | 内容 |
|---|---|
| seq | 616 |
| ack | 205 |
| rwnd | 5 |
| 数据部分 | 变化 |
|---|---|
| 接收窗口 | 8 -> 6 -> 8 |
| 发送窗口 | 5 -> 5 |
| 字段 | 内容 |
|---|---|
| seq | 205 |
| ack | 618 |
| rwnd | 8 |
超时重传机制
主机每次发出一次 TCP 段时都会设立一个计时器,在计时器范围内未收到对方的确认报文,就会重新发送该 TCP 段并重置计时器,这个过程称为超时重传
这里有两种情况
- TCP 段在前往目的主机中丢失
发送方计时器超时,触发重传机制,目的主机第二次顺利接收到并返回 ACK
- TCP 段目的主机正确接收,返回的 ACK 在计时器范围内未收到
目的主机接收到 TCP 段后,差错控制,并写入 2 B 数据返回 ACK , ACK 在返回发送方路程中丢失,发送方计时器超时触发重传,此时目的主机正确接收,但是比对自身记录的期待值发现这 2 B 数据在已正确接收的范围内,于是丢弃该段并再次发送 ACK ,此 ACK 内容和第一次发送的 ACK 内容相同
快重传机制
对于推迟重传机制,仍有部分缺点,例如:
假设发送方发送窗口为 4 并向接收方连续发送 4 份 TCP 段,设为 1 号、 2 号、 3 号、 4 号,由于不可抗因素, 2 号段在发送路程上丢失,此时接收方只顺利接收 1 号、 3 号、 4 号段,此时接收方由于接收的数据并不连续,此时返回的 ACK 内的 ack 字段仅在收到的 TCP 段 seq 字段的基础上加一,接收窗口也只减一; ACK 到达发送方时由于确认号仅加一且接收方接收窗口仅减一,于是发送窗口也只能减一,此时发送方发送窗口为 3 ,由于这四个数据在发送时都设置的超时重传计时器,且窗口内已无未发送数据,于是此时发送方只能等待计时器超时,并且没有任何动作,直到计时器超时才会重新发送这三个数据,而接收方也在等待 2 号数据,等待重传后收到三个数据检查发现后两个数据已经正确接收,于是丢弃,只接收 2 号数据,完成窗口移动……
由上述例子可以得出,推迟重传机制在发送多个报文段的过程中,如果其中个别报文段丢失,之后的超时重传机制会导致大量的时间浪费和性能浪费
面对这种情况,可以采用快重传机制解决
快重传需要使用立即确认机制(即在收到 TCP 段后立刻发送 ACK )
对于上面的例子,在快重传机制下,收到 1 、 3 、 4 号段后会立刻发送 ACK ,这三个 ACK 的确认号都是一样的,在快重传机制下,如果发送方接收到连续 3 个确认号相同的 冗余 ACK [1] ,就会立刻重发对应的报文段( ACK 段内 ack 字段指向的对应 seq 字段的数据,也就是丢失的那个数据),也就是重传 2 号段,接收方接收到缺失的报文段后,就继续完成对应的流程……
快重传机制大大提升了效率,但仍有缺陷,快重传机制仅适合处理丢失一个报文段的情况,若丢失多个报文段,快重传机制就可能会失效
TCP 拥塞控制
拥塞控制主要有四种算法:慢开始算法(解决网络严重拥塞的情况)、拥塞避免算法、快重传、快恢复算法(解决网络轻微拥塞的情况)
并引入机制:拥塞窗口( cwnd )
- 流量控制和拥塞控制的区别
| 流量控制 | 拥塞控制 |
|---|---|
| 控制端到端的数据发送量,是“局部的” | 控制整个网络中每台主机的数据发送量,降低路由器负载,是“全局的” |
如何判断网络拥塞
发出的每个报文段,都能顺利地收到 ACK 确认——不拥塞
发出的报文段未能按时收到 ACK ,引发超时重传——拥塞
收到冗余 ACK ,引发快重传——有点拥塞
如果检测到网络拥塞怎么办?
迅速减少发送的数据量
严重拥塞就迅速减小拥塞窗口
有点拥塞就适当减小拥塞窗口
注意
拥塞控制考题特点:
常与“流量控制”综合考察,此时需要考虑接收窗口大小
通常只涉及单向传输( TCP 连接双方只有一方发送数据)
通常默认每个 TCP 报文段都以最大段长 MSS 满载数据
拥塞窗口的大小常以“ MSS 的倍数”作为单位(例如此时 MSS 为 1000 B ,则拥塞窗口的大小单位为 2 则拥塞窗口的大小为 MSS 的 2 倍,即 2000 B )
接收方收到一个报文段,会“立即确认”(能够引发快重传机制,可以考察到对应的内容),而不是“推迟确认”
慢开始、拥塞避免算法
假设下面的例子中接收方的接收窗口无限大,这样发送窗口的上限就只取决于拥塞窗口的大小
根据上图解释:
开始时 cwnd 为 1 ,随着每次收到 ACK , cwnd 就会加 1 (效果为每过 1 个 RTT 的时间, cwnd 就会翻一番),直到 cwnd 大于等于 ssthresh ,此时就会进入拥塞避免算法,此时无论收到多少 ACK ,每过 1 个 RTT 只会增加 cwnd 一次
当 RTT = 12 时,假设此时发生了严重拥塞(发送的数据报有部分超时或丢失导致超时重传)此时会迅速减少 cwnd 到 1 并且将 ssthresh 设置为当前 cwnd 的一半( ssthresh 不能小于 2 )图中为 12 ;如果是收到冗余 ACK 那么 cwnd 不会迅速下降到 1
于是重新开始慢开始算法,直到某次发送 8 数据 ACK 后,由于 8 再翻倍是 16 大于了 ssthresh ,这里只会将 cwnd 增加到 ssthresh 然后进入拥塞避免算法
- 术语解释
ssthresh :慢开始门限(正规翻译) / 拥塞控制阈值(真题术语)
慢开始算法: cwnd 值从 1 开始,每收到 1 个 ACK ,就让 cwnd + 1 (当 时适用)
拥塞避免算法:在一个 RTT 内,即使收到多个 ACK ,也只能让 cwnd + 1 (当 时适用)
快重传、快恢复算法
和慢开始、拥塞避免算法前期处理类似,但是遇到拥塞后的处理方法不同
- 术语解释
快重传:当发送方收到 3 个确认号相同的冗余 ACK 时(至少收到 4 个相同的 ACK ),立即重传对应报文段
快恢复:一旦发生快重传,就将阈值、 cwnd 都设为当前 cwnd 的一半,然后切换为“拥塞避免算法”
接收方接收到的第一个 ACK 不属于冗余 ACK ,只有当接收到的第二个 ACK 和第一个 ACK 完全相同时,才会开始计数,若后续收到的 ACK 与第一个 ACK 不同,就会重新开始计数,即至少需要收到连续 4 个完全相同的 ACK 才会触发重传 ↩︎
更新日志
7e3ba-于f3bde-于49bda-于084c2-于4256a-于a08ee-于4f538-于0400b-于ff2c4-于c57fa-于c1978-于
