直接上图
三次握手
为什么是三次握手?
- 三次握手的首要原因就是不会建立历史连接
想象一个场景客户端向服务端发送一个SYN,但是被网络阻塞住了,然后客户端又发送了一个新的SYN,这时旧的SYN比新的SYN先到达了服务端,服务端收到后回复ACK/SYN给客户端,但是这时发的ACK的确认号与客户端期望的确认号是不一样的,客户端会发送一个RST去终止连接。这就是三次握手解决历史连接的方式。用图表示就是
为什么不是二次握手? 如果是二次握手的话那么SYN发过来的话,服务端就会进入到ESTABLISHEN状态,虽然客户端收到回复确认是历史连接了,因为服务端已经进入了ESTABLISHEN状态是能进行资源的发送的,也就是已经建立了历史连接了
- 第二个原因是同步双方初始序列号
TCP通信双方是要维护一个序列号的,有了序列号的好处就是
- 避免重复数据
- 接收方可以实现按序接受
- 可以标识发送出去的数据包中, 哪些是已经被对方收到的(通过 ACK 报文中的序列号知道)
因此去建立连接的时候通信双方也需要将各自的初始序列号进行发送(SYN中携带),当客户端向服务端发送SYN时需要服务端回复ACK来应答,而服务端也需要发送SYN来告知初始序列号,客户端也需要发送ACK进行应答。
为什么不是四次握手? 服务端收到SYN进行应答时的ACK发送和发送自己的初始序列号SYN是可以一起发出的。
- 最后一个原因就是减少资源浪费
如果是两次握手的话,客户端发送一个SYN因为网络阻塞住了,客户端没有收到服务端的ACK,会重新去发送SYN,而二次握手服务端没收到一个SYN就会主动建立一个链接,这是很大的资源浪费。
四次挥手
四次挥手的状态变化
- 客户端主动断开向服务端发送一个FIN数据包,进入
FIN_WAIT1 状态 - 服务端收到后回复一个ACK,并进入
CLOSED_WAIT 状态,并传输未发送完的数据传输完之后 - 客户端收到回复后进入
FIN_WAIT2 状态 - 服务端 发送FIN数据包并进入
LAST_WAIT 状态 - 客户端收到FIN数据包后回复ACK进入
TIME_WAIT 状态,服务端收到ACK后进入CLOSED 状态,客户端在等待2MSL之后也进入CLOSED 状态
断开连接与建立连接为什么会差一次
建立连接时确认回复ACK和发送SYN是可以同时进行的,但是断开连接时第一次回复ACK和客户端发送FIN是不能同时进行,因为虽然服务端确定客户端要断开连接了,但是不代表服务端没有数据需要发送了。
为什么是2msl
msl 是 Maximum Segment Lifetime,报文最大生存时间
因为客户端发送ACK,服务端可能收不到,他会重发FIN给客户端,然后客户端重发ACK,2msl则是保证产生的报文会在网络中消失 注 : 2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时。
学习资料
两张动图-彻底明白TCP的三次握手与四次挥手 小林coding
|