文章目录
- [UDP 协议](#UDP 协议)
- [TCP 协议](#TCP 协议)
-
- TCP的核心机制
-
- [1. 确认应答](#1. 确认应答)
- [2. 超时重传](#2. 超时重传)
- [3. 连接管理](#3. 连接管理)
- [4. 滑动窗口](#4. 滑动窗口)
- [5. 流量控制](#5. 流量控制)
- [6. 拥塞控制](#6. 拥塞控制)
UDP 协议
学习一个网络协议, 只要就是学习数据格式 , 报文格式
0 15 16 31
+----------------------+----------------------+
| 16位源端口号 | 16位目的端口号 |
+----------------------+----------------------+ ← 8字节
| 16位UDP长度 | 16位UDP检验和 |
+----------------------+----------------------+
| |
| 数据(如果有) |
| |
+---------------------------------------------+
UDP 使用简单有效的CRC校验和(循环冗余校验)
如果接收时根据数据的内容, 按照同样的算法算一遍校验和, 如果发生了改变, 就可以认为数据网络传输中出错了
TCP 协议
0 15 16 31
+------------------------+------------------------+
| 16位源端口号 | 16位目的端口号 |
+-------------------------------------------------+
| 32位序号 |
+-------------------------------------------------+
| 32位确认序号 |
+------------------------+------------------------+
|4位 | 保留 |U A P R S F| 16位窗口大小 |
|首部| (6位) |R C S S Y I| |
|长度| |G K H T N N| |
+------------------------+------------------------+
| 16位检验和 | 16位紧急指针 |
+------------------------+------------------------+
| 选项 |
+--------------------------------------------------+
| 数据 |
+--------------------------------------------------+
TCP最核心的机制, 就是"可靠传输"
不能做到百分百的送达
只能尽可能的使数据能送达对面
- 能感知对方是否收到
- 如果发现对方没收到, 就要进行重试
TCP的核心机制
1. 确认应答
感知对方是否收到
接收方收到数据之后, 就要给发送方, 返回一个"应答报文"(ack)
由于TCP是面向字节流的, 每个字节都有一个独立的编号, 字节和字节之间, 编号是连续, 递增的
序号表示的是 TCP 数据包载荷中的第一格字节的序号
在应答报文中, 针对之前收到的数据进行对应的编号, 称之为 TCP 的确认序号
确认序号, 会按照收到的数据的最后一个字节序号+1的方式来填写
标志位中的ACK会变1
乱序重排
收到的数据包根据序号重新排列, 确保收发数据一致
2. 超时重传
网络传输中, 数据可能会丢失
超时重传机制就是
发送方在规定时间内没有收到ACK, 就会认为数据丢失,进行重传
丢包的两种情况:
- 数据包丢了
- ACK丢了
发送方没办法区分, 只要没收到ACK, 都要重传
具体细节
接收缓冲区:
- 接收方收到的数据先放入缓冲区, 如果收到重复的数据, 直接丢弃即可
重传时间不固定:
- 第一次第二次重传时间为t1, t2, 且 t2 > t1
- 经过第一次的重传, 数据包的到达率会大大增加, 所以之后的时间可以增加
- 如果经过多次重传后还是到达不了, 就是说明网络可能比较拥堵, 需要更长的等待时间
重传次数有限制:
-
如果经过多次重传后还是没有到达, TCP会发复位报文, 试图重置连接
-
如果复位报文还是收不到就会断开连接
参数自适应:
- 以上参数都不是具体的数字,会根据网络实况进行动态调整
3. 连接管理
一、三次握手(建立连接)
-
握手是什么?
比喻:像打招呼一样,没有实际载荷,只是报头。
实际操作:发送只有报头(无数据)的数据包。
-
三次握手流程
双向操作:双方都要确认彼此的发送和接收能力。
具体过程:
- SYN:客户端发送同步请求(SYN)包,表示请求建立连接。
- SYN+ACK:服务端收到后,回复SYN+ACK,表示同意连接并确认收到请求。
- ACK:客户端再发一个ACK,确认连接建立。
本质:四次交互,中间两次(SYN+ACK)合并为一次,变成三次握手。
-
三次握手的意义
验证链路是否通畅
确认双方发送/接收能力正常
协商关键参数
- 如:起始序号,防止过期数据影响当前通信
二、四次挥手(断开连接)
-
挥手是什么?
断开连接:双方各自删除对端信息,保证连接彻底关闭。
-
四次挥手流程
FIN:一方主动发起断开(FIN包),表示不再发送数据。
ACK:对方回复ACK,确认收到断开请求。
FIN:对方也发送FIN,表示自己也要断开。
ACK:主动方再回复ACK,确认断开。
-
为什么不能合并?
握手时,SYN和ACK都由内核自动处理,时机一致,所以能合并。
挥手时,ACK由内核控制,FIN是应用程序触发(如调用close),时机不一定一致,所以通常不能合并。
4. 滑动窗口
滑动窗口基本概念
发送缓冲区示意图:
┌─────────────────────────────────────────────────────┐
│ 已确认 │ 已发送未确认 │ 可发送未发送 │ 不可发送 │
│ 数据 │ (滑动窗口) │ (滑动窗口) │ 数据 │
└─────────────────────────────────────────────────────┘
↑ ↑ ↑ ↑
窗口后沿 窗口位置 窗口前沿 缓冲区末尾
窗口大小
- 一次最多可以发送但未被确认的数据量(窗口)。
窗口滑动
- 收到一个ACK后,窗口向后移动,腾出空间继续发新的数据。
- 窗口的"大小"不变,"位置"改变。
效率提升
- 批量发送,合并等待ACK的时间,提升带宽利用率。
快速重传
丢包场景
- 某个包丢失后,后续包仍然可以到达接收方。
- 确认序号后一个ACK能涵盖前一个ACK的意义
快速重传
- 接收方收到后续数据,但前面的数据没收到,会重复发送同一个ACK号。
- 发送方如果连续收到3个相同的ACK,立即重传丢失的数据包(无需等超时)。
优点
- 只重传丢失的数据包,不影响已到达的数据包。
- 提高了丢包场景下的恢复速度。
5. 流量控制
滑动窗口的窗口大小直接影响传输性能
但窗口大小不能无限大,因为通信是双方的事,发送方快了,也要确保接收方能处理得过来。
接收缓冲区
定义:内核中的内存空间,每个 socket 对象都有一个接收缓冲区。
类似阻塞队列:生产者-消费者模型。
-
生产者:发送方
-
消费者:接收方应用程序
-
如果发送速度快、消费速度慢,缓冲区就会满。
-
缓冲区满了再强行发数据会丢包。
反向制约发送方
- 让接收方的处理能力,反向制约发送方的发送速度。
- 实现方式:定量反馈------根据接收缓冲区剩余空间大小,动态调整窗口大小。
窗口大小的动态调整
- 空闲空间大:应用程序处理快,窗口可以设置大些,允许发送方多发数据。
- 空闲空间小:应用程序处理慢,窗口设置小些,限制发送方发数据。
TCP中的反馈机制
- 接收方收到数据后,会把接收缓冲区剩余空间大小,通过ACK包反馈给发送方(16位窗口大小)。
- 发送方根据这个窗口大小,调整自己的发送窗口。
ACK与窗口大小
-
当标志位
ACK=1时,窗口大小字段有效。 -
该字段16位,最大表示范围为64KB。
-
可以通过TCP选项中的
窗口扩展因子
扩大窗口大小:
- 发送方窗口大小 = 窗口大小字段 << 窗口扩展因子
缓冲区满了怎么办?
- 如果接收缓冲区满了(窗口大小=0),发送方就暂时不发送数据。
- 但这样会有问题:不发数据就没有ACK,双方陷入等待。
- 解决方法:
- 发送方会周期性发送窗口探测包(载荷为空),触发接收方回复ACK,查询缓冲区剩余空间。
- 接收方消费了一定数据后,窗口不为0时,会主动发送窗口更新通知的数据包,告知发送方窗口已变大,可以恢复数据发送。