目录
UDP协议
UDP与TCP对比

- UDP 首部很小,只占 8B
- UDP 每次传输一个完整的报文,不支持报文自动拆分、重装
- UDP 是无连接的、不可靠的(可靠性可以交给应用层处理),也不支持拥塞控制
- UDP 支持一对一(封装成单播 IP 数据报)、一对多传输(封装成广播 / 多播 IP 数据报)

- TCP 首部更大,占 20~60B
- TCP 支持报文自动拆分、重装,因此可以传输长报文
- TCP 是有连接的、可靠的、支持拥塞控制
- TCP 仅支持一对一传输(因为通信双方的传输层必须先建立连接)
UDP数据报

UDP检验

将原始的 48bit 数据分成三组 16bit 的数据依次进行二进制加法(最高位产生的进位需要回卷),然后将得到的中间结果进行取反,所得到的就是校验和。并将校验和和原始数据组合在一起成为新的数据发送。
接收方对传输过来的数据进行验证,同样将数据拆分为 16bit 的数据进行二进制加法,如果加法结果不全是1,那么就说明发生了比特错误。
依此为基础,就可以理解UDP的检验
发送方的传输层

- 传输层的 UDP 协议在计算检验和之前,先添加伪首部
- 把伪首部、首部、数据部分以 16bit 为一组,进行二进制加法(最高位产生的进位需要回卷)
- 将最终的加法结果逐位取反,就得到 16bit 检验和,将其填入 UDP 首部
- 去掉伪首部,并将 UDP 数据报交给网络层,封装成 IP 数据报
接收方的传输层

- 网络层向传输层递交 UDP 数据报
- 传输层在 UDP 数据报之前,添加伪首部
- 把伪首部、UDP 首部、数据部分以 16bit 为一组,进行二进制加法(最高位产生的进位需要回卷)
- 如果加法结果为全 1,说明没有比特错误,于是接收该 UDP 数据报,并根据目的端口号,向应用层递交报文。如果加法结果不是全 1,说明有差错,于是丢弃该 UDP 数据报
TCP协议

工作流程
三大阶段:
- 建立连接(三次握手)
- 数据传输
- 释放连接(四次挥手)

- 每次建立TCP连接,双方可以传输多个报文
- TCP是面向字节流的,无论传输多少个报文,对于TCP协议来说都是一连串字节流
- 在 TCP 连接建立过程中,客户端和服务器会在 SYN 报文段中通过 TCP 选项字段携带自己期望的 MSS 值(Maximum Segment Size,最大段长),进行 MSS 的协商。但如果一方未在 SYN 报文中通告 MSS,那么另一方会使用默认值 536 字节(IPv4 最小安全值)。
TCP报文段

序号(seq):标记数据部分的第一个字节在原始字节流中的位置
确认号(ack 或 ack_seq):表示序号在该确认号之前的所有字节都已正确收到
ACK:ACK = 0时,ack_seq无效,ACK = 1时,ack_seq有效
数据偏移:TCP首部长度,以 ×4B 为单位
填充:凑足 4B 的整数倍
URG:URG = 1时,表示当前TCP报文段为紧急数据,应尽快插队
紧急指针:紧急数据专用序号
PSH:PSH = 1时,表示希望接受方尽快回复
SYN:同步位。当SYN = 1时表示这是一个连接请求或连接接受报文。只有握手1、2的SYN = 1,其他的阶段都为0
FIN:终止位(Finish),当FIN = 1时,表明此报文段的发送方数据已发送完毕,要求释放传输连接。只有挥手1、挥手3的FIN = 1,其他的阶段都为0
窗口(rwnd 或 rcvwnd):16bit,表示接收窗口的大小。即从本报文段首部中的ack_seq算起,接收方还能接收多少数据
校验和:原理与UPD的校验和计算方式相似
连接管理具体流程
建立连接(三次握手)

- 握手1、2不携带数据,但还是要消耗一个序号。只有握手1、2的SYN = 1。只有握手1的ACK = 0
- 握手3可以携带数据。
- 如果握手3不携带数据,那么不消耗序号。
释放连接(四次挥手)

一开始数据传输是双向的,当客户进程A发出 挥手1 ,A-B 的数据传输通道就已经关闭了。但 B-A 的通道依然存在,因此 挥手2 依旧可以单向传输数据。当挥手3 发出,B-A的通道也关闭了,因此挥手4就不可以携带数据。
- 在 TCP 全过程中,只有挥手1、挥手3的 FIN=1
- 挥手1、挥手3即使不携带数据,也要消耗一个序号
- 挥手2可以携带数据
- 挥手4不可以携带数据
MSL(MAximum Segment Lifetime,最长报文短寿命),是由TCP协议规定的一个固定时间长度
为什么要服务器进程A要等待2MSL才会关闭连接?
因此网络是不稳定的,有可能挥手4的信息并没有传送到服务器进程B,这时候服务器进程B就会再次发送挥手3给服务器进程A,这是服务器进程A还在TIME-WAIT没有关闭,因此可以实现重发。如果重复收到了挥手3,那么计时器会重置。
TCP可靠传输与流量控制
序号
进程在建立连接时确定起始序号,数据传输过程中,每个字节对应一个序号
确认机制

- 累积确认规则:如果收到 ack_seq=n,说明序号在 n 之前的所有字节都已正确接收
- 返回 ACK 的时机 - 推迟确认:
-
- 推迟时间最多不能超过 0.5 秒(TCP 标准规定)
- 如果自己也有数据要传送给对方,立即返回 ACK 段,并 "捎带" 自己的数据
- 若连续收到两个长度为 MSS 的报文段,就应该立即返回 ACK 段
- 两种 ACK 段:
-
- 专门确认:一个 ACK 段只有 TCP 首部,而没有携带数据
- 捎带确认:一个 ACK 段顺道携带了数据,就是 "捎带确认"
重传机制

- 超时重传 :每发出一个报文段,就设置一个计时器。若计时器到期还没收到确认,就重传这一报文段,并重设计时器
- 快重传(冗余 ACK):
-
- 作用:让可能出错的报文段尽早重传,而不是非要等到超时再重传
- 配套机制:立即确认
-
-
- 每收到一个 TCP 报文段,就立即返回一个 ACK 段
- 即使收到一个失序报文段,也要立即返回 ACK 段(失序报文段会导致冗余 ACK)
-
-
- 当发送方连续收到三个确认号相同的冗余 ACK 时,就立即重传该确认号对应的报文段
TCP拥塞控制
流量控制:控制端到端的数据发送量,是局部的
拥塞控制:控制整个网络中每台主机的数据发送量,降低路由器负载,是全局的
如何判断网络拥塞?
- 发出的每个报文段,都能顺利地收到 ACK 确认 ------ 不拥塞
- 发出的报文段未能按时收到 ACK,引发超时重传 ------ 严重拥塞
- 收到冗余 ACK ,引发快重传 ------ 有点拥塞
如果检测到网络拥塞怎么办?
- 迅速减少发送的数据量
- 严重拥塞就迅速缩小拥塞窗口
- 有点拥塞就适当缩小拥塞窗口
算法

慢开始算法:cwnd 值从 1 开始,每收到一个 ACK,就让 cwnd+1(当 cwnd<ssthress 时适用)
拥塞避免算法:在一个 RTT 内,即使收到多个 ACK,也只能让 cwnd+1(当 cwnd≥ssthress 时适用)
当发生网络严重拥塞(超时重传)时,会适当改变门限ssthresh的值(ssthresh = cwnd / 2,但不能小于2),并将窗口改为1
慢开始算法:cwnd 值从 1 开始,每收到一个 ACK,就让 cwnd+1(当 cwnd<ssthress 时适用)
拥塞避免算法:在一个 RTT 内,即使收到多个 ACK,也只能让 cwnd+1(当 cwnd≥ssthress 时适用)
当发生网络拥塞(冗余ACK)时,会适当改变门限ssthresh的值(ssthresh = cwnd / 2,但不能小于2),适当的缩小拥塞窗口(cwnd /= 2)