TCP 三次握手 四次挥手
TCP三次握手的过程
TCP为了实现面向连接的可靠传输使用了三次握手和四次挥手的机制。三次挥手的过程是:
- 客户端向服务器发送一个SYN报文进入
SYN_SEND
状态,其中会随机一个序列号x,并且将SYN的标志位设置为1.该报文不会携带任何应用层数据。该报文的目的就是客户端请求连接的建立 - 服务器收到客户端的SYN报文,会回复一个SYN-ACK报文 进入
SYN_RCVD
状态,目的是告诉服务器表示同意建立连接,并且也会初始化一个随机序列号y,并将syn和ack标志位都设置为1,ack号为x+1。该报文也不会携带应用层的数据 - 客户端收到服务器的SYN-ACK报文后,向服务器发送一个ACK报文,客户端进入
ESTABLISED
状态。ACK标志位设置为1,ACK为y+1,这个报文可以携带应用层数据,这个报文的意义也是告诉服务器连接已经建立成功,可以发送数据了
TCP为什么是3次挥手,而不是2次,4次?
如果2次挥手就能建立TCP连接,也就是客户端向服务器发送一个SYN报文后,服务器收到SYN报文,服务器这边就进入了可以发送数据的状态,而客户端收到服务器的ACK后也就进入了可以发送数据的状态。然后如果客户端向服务器发送的SYN遭遇了堵塞,因此服务器重启新发送了一个SYN。然而服务器收到第一个SYN后就建立了一个连接,而客户端收到第一个SYN的ACK后发现并不是自己期待的就会废弃掉,服务器收到第二个SYN后又会建立新的连接并发现新的ACK,这个时候客户端收到ACK就会建立TCP连接,那么服务器就多了一个没有意义的连接,会造成资源浪费。并且如果服务器发送的ack丢失,服务器并不知道客户端是否收到ack,所以会继续发送数据,造成资源浪费
四次挥手就是在服务器将syn+ack拆分成了两步,这个是没有必要的,放在一步效率更高
TCP四次挥手的过程
处于连接状态的客户端和服务器都可以发起关闭连接的请求
- 第一次挥手,客户端向服务器发起FIN报文,客户端从ESTABLISHED状态变更为FIN-WAIT-1状态。客户端进入这个状态后不再发送数据,但是还可以接收来自服务器的数据
- 第二次挥手:服务器收到该报文,就会向客户端发送ACK报文,服务器从
Established
状态进入Closed_wait
状态。确认客户端不再能发送数据,但是服务器还有数据要发送。不会关闭连接 - 客户端收到服务器的ack报文后,进入到
FIN_WAIT_2
的状态 - 第三次挥手:服务器处理完剩余数据,向客户端发送FIN报文,进入
Last_ACK
状态。告知客户端服务器也不再发送数据了,不再需要保持连接了 - 第四次挥手:客户端发送ACK,客户端进入
Time_Wait
状态,等待2MSL之后变为closed状态。服务器收到ACK后确认关闭连接,也进入了CLOSED状态
客户端的状态变化:established-->FIN_wait_1 --> fin_wait_2 --> time_wait 等待2MSL--> Close
服务器的状态变化:established --> closed_wait --> last_ack --> closed
客户端有一个time_wait的状态主要是为了等待最后一个ack能够正确到达服务器,因为如果最后一个ack在传输过程中出错,就会触发重传机制,服务器向客户端发送最后一个fin报文,这是一个MSL时间,客户端在返回一个ACK,这又是一个MSL,所以需要两个MSL,也需要time_wait状态等待ack的顺利到达。
tcp必须是4次挥手断开连接。因为如果是3次,那就是把ack和fin和在一起了。但是断开连接时可能会有数据没有完全传输,需要等待数据传输完成才能发送fin。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Priska's blog!