TCP/IP 协议三次握手(Three Way Handshake)#
三次握手是用于建立客户端与服务器的 TCP 连接,确保连接是可靠的、同步的。
-
第一次握手:SYN
- 客户端向服务器发送一个 SYN(Synchronize)报文,表示请求建立连接。
- 客户端进入
SYN-SENT
状态,等待服务器响应。
客户端 - SYN ---> 服务器
-
第二次握手:SYN-ACK
- 服务器受到客户端的 SYN 报文后,回应一个 SYN-ACK(Synchronize Acknowledge)报文,表示接受并同意建立连接,同时也向客户端发送一个 SYN,请求建立反向连接。
- 服务器进入
SYN-RECEIVED
状态。
客户端 <--- SYN-ACK - 服务器
-
第三次握手:ACK
- 客户端收到服务器的 SYN-ACK 报文后,发送一个确认 ACK 报文,表示连接已建立。
- 客户端进入 ESTABLISHED 状态,服务器收到 ACK 后也进入
ESTABLISHED
状态。
客户端 - ACK ---> 服务器
三次握手的目的#
确保双方能正确发送和接收数据,并同步双方的序列号。
解释 TCP 需要三次握手的原因#
三次握手是为了确保双方都有发送和接收的能力(双方都要确认对方有发送和接收的能力)。
- 第一次握手:客户端告诉服务器,自己可以发送数据。
- 第二次握手:服务器告诉客户端,自己可以收发数据。
- 第三次握手:客户端告诉服务器,自己可以接收数据。
TCP/IP 协议四次挥手(Four Way Handshake)#
四次回收用于断开客户端与服务器的连接,由于 TCP 是全双工协议,连接断开时需要双方各自关闭发送和接收通道,因此需要四次挥手来完成断开操作。
-
第一次挥手:FIN
- 客户端发送 FIN(Finish)报文,表示不再发送数据,但仍可以接收数据。
- 客户端进入 FIN-WAIT-1 状态。
客户端 - FIN ---> 服务器
-
第二次挥手:ACK
- 服务器受到客户端的 FIN 报文后,发送一个 ACK 报文,表示确认受到 FIN 报文,但服务器仍可能有数据需要发送。
- 服务器进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态。
客户端 <--- ACK - 服务器
-
第三次挥手:FIN
- 服务器完成数据发送后,向客户端发送 FIN 报文,表示数据传输结束,准备关闭连接。
- 服务器进入 LAST-ACK 状态。
客户端 <--- FIN - 服务器
-
第四次挥手:ACK
- 客户端收到服务的 FIN 报文后,发送一个 ACK 报文,表示确认关闭连接。
- 客户端进入 TIME-WAIT 状态,等待一段时间(一般为 2 * MSL,最大报文存活时间)后,正式关闭连接,进入 CLOSED 状态。服务器在收到 ACK 后立即进入 CLOSED 状态。
客户端 - ACK ---> 服务器
简述 TCP 拥塞控制算法#
- 慢启动:建立连接后,初始化发送窗口大小,随着每次发送 ACK 到达,窗口大小呈指数级增长,直到达到拥塞阀值。
- 拥塞避免:当窗口大小达到阀值后,发送方每次只增加一个 MSS。
- 快速重传:在没有等待超时的情况下,接收方连续发送 3 个重复的 ACK 时,发送方立即重传相应的报文段。
- 快速恢复:当进入快速重传阶段后,发送方将窗口减半。
简述 MTU 和 MSS#
MTU(Maximum Transmission Unit):最大传输单元,表示网络层一次能传输的最大数据包大小,以太网通常为 1500 Byte。
MSS(Maximum Segement Size):最大报文段大小,TCP 层能够发送的单个数据段的最大字节数,通常是 MTU 减去 TCP/IP 头部大小。
TCP 粘包问题#
当客户端发送多个数据包给服务器时,服务器底层的 TCP 接收缓冲区受到的数据为粘在一起的。
TCP 底层通信是面向字节流的,面向连接的协议,TCP 保证发送数据的准确性和顺序性,字节流以字节为单位。
假设 TCP 缓冲区的大小为 10 个字节,当发送 4 个字节的数据("aaaa"),缓冲区还剩余 6 个字节的空闲空间,再次发送 7 个字节的数据("bbbbbbc"),则客户端第一次接收的数据是 "aaaabbbbbb"
,剩余 1 个字节的数据未发送,等待下一次发送。
TCP 粘包产生的原因#
多个小数据包在传输过程中粘在一起,接收端无法区分这些包的边界,导致接收到的数据合并在一起。
- (发的太快)当客户端的发送频率远高于服务器的接收频率。
- (发的太少)TCP 底层的安全和效率机制,其不允许字节数特别少的小包发送频率过高,TCP 会在底层累计到一定大小才一起发送。(Nagle)
- (缓冲区残留)发送端的缓冲区中有上一次未发送完的数据,或接收端的缓冲区中有未取出的数据。
TCP 黏包处理的方式#
主要采用应用层定义收发包格式的方法,俗称切包处理
使用 TLV 协议#
TLV(Type Length Value)协议。
+---------+---------+---------+
| type | length | value |
+---------+---------+---------+
打包发送的数据,解包接收的数据。
使用分隔符#
在报文之间增加特殊字符
设置固定长度的报文#
规定报文的长度,接收方根据长度拆分。
TCP 实现全双工的方式#
- 独立的发送和接收缓冲区,通信双方都有一个发送缓冲区和接收缓冲区,通信双方在发送数据时可以接收数据,反之依然。
- 独立的序列号和确认机制,TCP 将要发送的数据流切分为多个报文段,每个报文段的字节都有唯一的序列号,确保发送的数据包在整个数据流中的位置,接收方可以根据序列号判断数据的正确顺序以及是否有丢包。
- 流量控制,TCP 通过控制滑动窗口机制调整发送速率,保证不会让接收方的缓冲区溢出(被数据淹没)。
- 拥塞控制,控制通过调节发送方的发送速率来防止网络过载。