三次握手
- 通过传输层的 tcp 协议建立网络连接时,走三次报文握手过程(总体上其实就是一次 tcp 握手)
- 一开始客户端和服务端都处于 CLOSE 状态
- 客户端发送一个 请求报文
- SNY=1, seq = x
- SYN=1 表示 tcp 标头中 SYN 位有效,表示当前为握手信号
- seq=x 表示当前请求的序列号为 x
- 然后客户端会处于 SYN-SENT 状态
- SNY=1, seq = x
- 服务端监听时,如果收到客户端的请求报文,会返回一个响应报文
- SYN=1 ACK=1 seq=y ack=x+1
- SYN=1 表示 tcp 标头 SYN 位有效,表示当前为握手信号
- ACK=1 表示 tcp 标头 ACK 位有效,表示当前为响应信号
- seq=y 表示当前响应报文的序列号为 y
- ack=x+1 在 ACK 位有效的前提下,表示当前请求是响应序列号为x的请求(针对要响应的请求的seq的值)
- 服务端会处于 SYN-RCVD 状态
- SYN=1 ACK=1 seq=y ack=x+1
- 客户端收到服务端的确认报文后,会再次发送一个确认收到服务端确认报文的报文
- ACK=1 seq=x+1 ack=y+1
- ACK=1 表示 tcp 标头 ACK 位有效,表示当前为响应信号
- seq=x+1 表示当前响应报文的序列号为x+1,是上一次握手信号的序列号+1
- ack=y+1 在 ACK 位有效的前提下,表示当前请求是响应序列号为y的请求(针对要请求的seq的值)
- 客户端会处于 ESTAB-LISHED 状态
- ACK=1 seq=x+1 ack=y+1
- 服务端收到客户端的确认报文,会处于 ESTAB-LISHED 状态
为什么不是两次?
- 如果客户端第一次发送连接请求报文,由于网络延迟,未能及时到达服务端
- 那么客户端会重新发多一次请求报文
- 此时第二次请求报文服务端进行了响应,服务端分配了资源等,和客户端开始进行数据交互
- 假设此时客户端第一次发送的请求报文又到了服务端
- 服务端同样对该报文进行响应,并且会分配资源,等待和客户端进行交互
- 但是这次不会有数据交汇,会白白兰浪费服务端的资源
- 如果是三次握手,那么第一次请求报文的响应报文到达客户端时,客户端发现根本不对,就会发送个复位的报文过去,让服务器撤销开辟的资源
四次挥手
- 客户端会发送一条客户端向服务端的结束连接信号
- FIN=1,表示 tcp 标头 FIN 位有效,表示当前请求是结束连接信号
- 在客户端收到服务端的响应后,此时客户端向服务端的单向数据通信结束
- 但是服务端可能还有一些数据需要继续发给客户端,所以不会断开
- 服务端完成剩余的客户端数据交互后,会发送一个服务端向客户端的结束连接信号
- 为啥 seq不是v+1呢? 因为在 CLOSE-WAIT 阶段可能会传输数据,所以数据不会连续
- 该结束信号是针对客户端发起的结束连接信号,所以 ack 还是 u+1
- 服务端收到客户端的响应后,此时服务端向客户端的单向数据通信结束
为啥要有 TIME-WAIT
- 可能服务端发送的结束报文由于网络延迟客户端未能收到或者丢失,导致客户端没有响应服务端的结束报文
- 服务端会重新发送一条结束报文
- TIME-WAIT 阶段就是等待这个可能会发送的结束报文