# TCP/UDP
# TCP
:传输控制协议(Transmission Control Protocol)
- 属于传输层协议,规定了网络上的主机之间如何传输数据。
- 采用 C/S 架构,需要一方作为服务器保持运行。
- 特点:
- 全双工通信。
- 面向连接:通信双方在通信之前要先建立连接,作为信道。
- 传输可靠:
- 会确认对方是否收到消息,如果未收到则自动重发。
- 可进行差错控制,如果对方收到的消息出错,则自动重发。
- 发送的数据包带有序号,接收方可按顺序处理。
- 可实现流量控制、拥塞控制。
- 大部分应用层协议都是基于 TCP 进行通信的,比如 HTTP、FTP、SMTP 等。
# 数据包结构
TCP 数据包的结构如下:
- Source Port :源端口,长度为 16 bit 。
- Dest Port :目标端口,16 bit 。
- Seq number :序列号,32 bit ,用于保证消息顺序。
- Ack number :确认号,32 bit ,表示期望收到的下一个序列号,用于标识符 ACK=1 的情况。
- Data offset :偏移量,4 bit 。表示 Payload 的起始坐标,即 TCP Header 的总长度。
- Reserved :保留给未来使用,3 bit ,默认值为 0 。
- Flag :标志符,9 bit 。每个 bit 代表一个标志位,默认值为 0 。
- NS
- CWR
- ECE
- URG=1 :表示该数据是紧急数据,应该被优先处理。
- ACK=1 :表示确认。
- PSH=1 :表示发送方应该立即将该数据打包成一个 TCP 数据包发送,接收方也应该立即将该数据上报给上层程序。
- TCP 模块在发送数据时,一般会等发送缓冲区满了,才打包成一个 TCP 数据包发送。同理,接收数据时也一般会等接收缓冲区满了才上报。
- 一般一个应用层的报文会被切分成多个 TCP 数据包发送,最后一个 TCP 数据包会设置成 PSH=1 。
- RST=1 :用于重新建立 TCP 连接,也可用于拒绝连接。
- SYN=1 :用于建立 TCP 连接,开始同步。
- FIN=1 :用于断开 TCP 连接。
- Window size
- Checksum :校验和,16 bit 。
- Urgent pointer
- Options
- Payload :有效载体,即该数据包要传递的实际数据。
- Payload 之前的其它数据都只是用于描述 TCP 数据包的元数据,称为 TCP Header 。
- 以太网中网卡的 MTU 通常设置为 1500 ,因此如果 TCP 报文超过该长度,转换成 IP 数据包时就需要拆分成多份。
# 建立连接
建立 TCP 连接时需要经过三个步骤,称为 "三次握手" :
- 主机 A 发送一个 SYN=1 的 TCP 包,表示请求连接。
- 主机 B 收到后,回复一个 SYN=1、ACK=1 的 TCP 包,表示允许连接。
- 主机 A 收到后,发送一个 ACK=1 的 TCP 包,表示正式建立连接。
- 主机 A 收到第 2 步发送的包时,证明了自己发送的包能被对方接收,而对方发送的包也能被自己接收,因此判断双方能够相互通信。
- 主机 B 收到第 3 步发送的包时,才判断双方能够相互通信。
主动连接方称为 client ,被动连接方称为 server 。
- 通信双方都要发送一个 SYN、一个 ACK 。
- 建立连接之后,双方便可以开始正式通信,发送任意个包含有效载体的 TCP 数据包。
# 断开连接
- 断开 TCP 连接时需要经过四个步骤,称为 "四次分手" :
- 主机 A 发送 FIN ,表示请求断开连接。
- 主机 B 收到后,先回复 ACK ,表示同意断开连接。
准备好了之后也发送 FIN ,请求断开连接。 - 主机 A 收到后,发送一个 ACK ,表示自己已经断开连接。
- 主机 B 收到后,正式断开连接。
- client、server 都可以主动断开连接。
- 通信双方都要发送一个 FIN、一个 ACK 。
# 传输数据包
# 重传
- 建立 TCP 连接之后,通信双方可以开始传输数据包。
- 发送方每发送一个数据包之后,都需要接收方回复一个包含相应序列号的 ACK 包,才能确认发送成功。
- 超时重传
- :如果发送方发送一个数据包之后,超过 RTO(Retransmission Timeout) 时间未收到 ACK 包,则重新发送原数据包。
- RTO 应该略大于 RTT 。例如 Linux 会根据网络实时的平均 RTT ,动态设置 ERO 。
- 往返时间(Round Trip Time ,RTT),表示从发出数据包到收到回复的耗时。是端到端延迟的两倍。
- 超时的常见原因:
- 网络延迟突然变大
- 发送的数据包丢失
- 回复的 ACK 包丢失
- 快速重传
- :如果发送方发送一个数据包之后,没有受到 ACK 包,但之后发送的 3 个数据包都收到 ACK 包,则认为前一个数据包发送失败,立即重传。
# 流量控制
- 滑动窗口
- :接收方将接收窗口的大小告诉发送方,发送方由此确定发送窗口,可以每次发送多个数据包,再等待确认。
- 这可以实现流量控制,控制传输速度。
- 发送窗口
- :指发送方能同时发送的数据包数,即最多允许多少个数据包等待确认,此时不允许发送新的数据包。
- 它不能超过网络允许带宽、接收方的接收缓冲区,否则会丢包。
- 发送窗口取决于接收窗口,近似相等
# 拥塞控制
网络拥塞:当网络延迟变大、发生丢包时,会引发超时重传,但重传的数据包又会增加网络负载,导致延迟更大、丢包率更高。
为了减轻网络拥塞,发送方会动态计算一个拥塞窗口,并限制发送窗口不能大于接收窗口或拥塞窗口。
BBR
- :Google 于 2016 年发布的一种 TCP 拥塞控制算法。在延迟超过 100ms 、丢包率超过 1% 的场景下,能在发送 TCP 包时明显提高吞吐量、降低延迟。
- 当网络链路拥塞时,传统的拥塞控制算法 Reno、Cubic 会将数据包放到缓冲区再发送,因此增加了延迟。而 BBR 算法会避免使用缓冲区。
- Linux 内核 4.9 加入了 BBR 算法,可通过 sysctl 启用。
- 拥塞控制算法只作用于 TCP 通信的一方,因此发送方、接收方可以采用不同的算法。
# UDP
:用户数据报协议(User Datagram Protocol)
- 特点:
- 全双工通信。
- 面向无连接。
- 传输不可靠。
- UDP 与 TCP 对比:
- UDP 没有 TCP 的诸多功能,更像是 IP 协议,只是简单地发送数据包。
- UDP 的开销更低。比如 TCP 需要一直运行一个服务器,而 UDP 适合用作即时通信、广播消息。
- 使用 UDP 时,如果需要差错控制等可靠性,可由应用层实现。
- 少部分应用层协议是基于 UDP 进行通信的,比如 DHCP、DNS、SNMP、RIP 等。