Open
Description
定义
这两个都是传输层的协议,位于 OSI 七层协议的第四层。
TCP (Transmission Control Protocol )传输控制协议,是面向连接的,保证数据可靠传输的协议,具有超时重传、拥塞控制等功能。
UDP(User Datagram Protocol)用户报文协议,是面向报文的无连接传输层协议。
TCP 三次握手
- 首先,客户端发送一个 SYN 报文给服务器,里面包含初始序列号(例如:x),此时客户端处于 SYN_SEND 状态
- 服务端收到报文后,如果同意建立连接,就回复 SYN 包,设置 ACK 标志位,给客户端的序列号 x + 1,并选择一个初始序列号 y,此时服务端处于 SYN_RECV 状态
- 客户端收到后,回复一个 ACK 标志的报文给服务端。这个报文里会给服务端的初始序列号 y + 1。此时客户端处于 ESTABLISHED 状态。服务端收到 ACK 报文后,也会进入 ESTABLISHED 状态,三次握手完成。
由此延伸出来的问题:
- 为什么需要三次握手,两次不可以吗?
三次握手是为了保证客户端和服务端两方都知道对方既能收又能发。
如果只有两次的话,服务端收到客户端的报文后,回一个 ack 给客户端,此时服务端认为请求已经建立了,可以发送数据了。但是如果网络出问题,服务端的应答报文并没有到客户端那边,此时客户端不知道服务端的情况,它会忽略服务端发来的其它报文,一直等待确认报文,而服务端以为已经建立连接了,一直发送数据,此时就可能产生死锁。 - 第三次握手如果客户端发送的 ACK 报文因为网络问题丢包,服务端一直没有收到怎么办?
服务端会有一个超时重传计时器,如果在一定时间内没有收到客户端发的报文,服务端会重传自己的 SYN + ACK 给客户端,客户端这边收到后,就会重发 ACK 给服务端,直到服务端这边收到 ACK 报文为止。
TCP 四次挥手
- 首先,客户端发送 Fin 报文给服务端
- 服务端收到后,回复一个 ACK 报文给客户端,表示服务端已经知道客户端要关闭了,但此时服务端可能还有待发送数据。
- 等服务端处理完后,就发送一个 FIN 报文给客户端
- 最后客户端再回复一个 ACK 给服务端,此时客户端需要等待 2MSL 的报文生存时间,然后才断开。服务端收到客户端的报文后就断开了连接
由此延伸出来的问题: - 为什么要等待 2MSL 才进入 close 状态?
因为我们必须假设网络是不可靠的,可能最后一个 ack 报文丢失了。TIME_WAIT
状态就是为了出现错误,重发丢失的报文。比如服务端一直没有收到 ack,那它就会一直重发 FIN 报文,而客户端收到后,就会回复 ACK ,然后继续等待 2MSL 的报文生存时间,如果过了后没有收到服务端的报文,客户端就推断服务端已经成功接收了,然后就可以进入 close 状态了。 - 如果连接建立了,但是中途客户端出现故障了怎么办?
TCP 有设置一个计时器,服务端每次收到客户端的报文都会复位这个计时器,如果发现一直没有客户端的报文,服务端会发送一个探测报文段,每隔 75s 发送一次,如果连续 10 次都没有回应,服务端就认为客户端出问题了,然后就可以断开连接。
TCP 的拥塞控制
拥塞控制就是当网络出现拥堵时,通过调整发往网络中的数据包来减少拥堵,它作用的是整个网络。拥塞控制的关键是控制发送方的发送速率——拥塞窗口大小,主要有以下四个算法:
慢启动
: 刚开始发送时,拥塞窗口大小(cwnd)设置为一个较小的值(通常是初始大小,1-3个最大报文段),随后每收到一个 ACK 报文,拥塞窗口大小会加倍,这样发送速率是呈指数增长的,当到达慢启动阈值时,就进入拥塞避免算法。拥塞避免
:在这个阶段,为了避免窗口的快速扩张,每经过一个往返时间 RTT,拥塞窗口大小增加 1 个最大报文段,相当于将发送速率由指数增长调整为线性增长,这样保持直到网络拥塞或者数据传输完成。快重传
:这个算法用于网络拥塞时快速检测丢失的报文段,它规定当发送方连续收到三个相同的确认报文段时,客户端就会立即重传丢失的报文段,而不用等待超时重传计时器到期。这个机制一定程度上可以减少报文段重传的延迟。快恢复
:当发送方处于快重传模式时,它会将慢启动闸值设置为当前拥塞窗口大小的一半,并将拥塞窗口大小设置为新的慢启动闸值加上三个最大报文段。此时发送方开始重新传输丢失报文段,并根据收到的重复确认报文段来调整拥塞窗口的大小。当发送方收到新的报文段时,就退出快恢复模式,重新进入拥塞避免阶段。
TCP 的流量控制
流量控制的目的在于防止发送方速率过快,接收端处理不过来,是为了平衡发送方和接收方的数据处理能力。实现流量控制的关键是滑动窗口
。
接收窗口(Receive Window)
:接收方为每个连接分配一个接收缓冲区,并通过 TCP 报文段的窗口字段(Window Field)告知发送方当前可用的缓冲区大小。这个值被称为接收窗口(rwnd),用于限制发送方发送数据的速率。接收窗口的大小可以根据接收方处理能力和网络状况进行动态调整。滑动窗口(Sliding Window)
:发送方需要根据接收方提供的接收窗口大小(rwnd)和本地拥塞窗口大小(cwnd)来确定实际的发送窗口。实际发送窗口大小取 rwnd 和 cwnd 中的较小值。发送方只能发送发送窗口内未确认的数据。当发送方收到确认报文时,滑动窗口会向前移动,从而允许发送更多数据。窗口更新
:当接收方处理完接收缓冲区中的数据后,它需要发送一个新的确认报文,更新窗口字段,以通知发送方可以发送更多数据。这个过程被称为窗口更新。接收方可以根据自己的处理速度和网络状况,动态调整接收窗口大小,从而影响发送方的发送速率。零窗口探测
:在某些情况下,接收方的处理速度较慢,导致接收窗口变为零。这意味着发送方需要暂停数据发送。当接收方处理完缓冲区内的数据后,它会发送一个窗口更新报文,通知发送方恢复数据发送。为了防止发送方长时间处于停止发送状态,TCP 引入了零窗口探测机制。当发送方收到零窗口更新后,它会周期性地发送探测报文,以检测接收窗口是否恢复。
TCP 的应用
- FTP 文件传输
- HTTP/HTTPS
UDP 的特点和应用
- 无连接,面向报文
- 不保证消息交付(没有重传超时机制)
- 不保证交付顺序(意味着不会发生队头阻塞)
- 不跟踪连接状态(不必像 TCP 那样三次握手)
- 没有拥塞控制(有啥发啥,不管结果)
UDP 因为以上特点,适用于一些对延迟要求较高的场景,比如直播、视频和音频等多媒体通信
总结
TCP 和 UDP 的对比:
区别 | TCP | UDP |
---|---|---|
连接 | 需要三次握手建立连接 | 无连接 |
数据传输方式 | 字节流 | 报文 |
可靠性 | ack 确认机制,超时重传,拥塞控制 | 不可靠,以恒定的速度发数据 |
连接数 | 一对一 | 一对一,一对多,多对多 |
首部大小 | 大概 20 ~ 60 字节 | 8 字节,开销小 |
传输速度 | 慢 | 快 |
使用场景 | 文件传输 | 实时通讯,视频会议,直播等 |