TCP三次握手建立连接,四次挥手断开连接
1.三次握手建立连接:
先来解释一下上图中的几个大写字母代表什么含义:
SYN:同步序列编号(Synchronize Sequence Numbers),代表请求创建连接,所以在三次握手中前两次要SYN = 1,表示这两次用于建立连接。
FIN: Finish,表示请求关闭连接。在下述的四次挥手时,FIN发了两遍,是因为TCP连接是双向的,所以一次FIN只能关闭一个方向。
ACK:Acknowledgement,即确认字符,代表确认接受。从图里可以看见,不管是三次握手还是四次挥手,在回应的时候都会加上ACK = 1,这就表示消息接收到了。
我们一起来理一下三次握手建立连接的思路:
- 第一次握手:在建立连接时,客户端发送SYN包(SYN=1)到服务器,并进入了SYN_SENT状态,等待服务端的确认;
- 第二次握手:服务端接收到SYN包后,必须确认客户端的SYN,同时自己也发送一个SYN包,即SYN+ACK包,此时服务端进入了SYN_RCVD状态;
- 第三次握手:客户端收到服务端的SYN+ACK包,向服务端发送一个确认包ACK,此包发送完毕后,客户端和服务端就进入了ESTABLISHDE状态,完成三次握手。
四次挥手
2.四次挥手断开连接:
- 假设是客户端主动关闭并停止发送数据,就会向服务端发送一个FIN包,表示要关闭一个方向的连接,此时客户端进入FIN_WAIT_1状态;
- 服务端接收到后,发出确认报文(ACK=1),这时服务端就进入了CLOSE_WAIT状态,这时候处于半关闭状态,即客户端已经没有数据要发送了。但是服务端若发送数据,客户端还会接收。这个状态要持续一段时间,就是整个CLOSE_WAIT状态;
- 客户端收到服务端的确认请求后,此时客户端就进入了FIN_WAIT_2状态;
- 这时服务端也要关闭,服务端会发送一个FIN包,此时服务端就进入了LAST_ACK(最后确认)状态,等待客户端的确认;
- 客户端在接收到服务端的关闭请求后,会回复一个确认ACK。此时客户端就进入了TIME_WAIT状态。注意:此时连接并没有断开,还要经过2MSL(最大报文生命周期)后才进入CLOSE状态;
- 服务端只要收到了客户端发出的确认,立即进入CLOSE状态,就结束了整个连接。
问题:为什么需要三次呢(为什么不用两次建立连接呢)?
如果发送两次就可以建议连接,那么客户端只需要发送一个连接请求,服务端接收到连接请求后再回复一个确认消息,就会建立一个连接。但这样是不安全的。如果SYN请求在网络中网络中延迟到达,这时候假如客户端退出了,服务端收到的第一个SYN请求就无法保证客户端的数据收发能力,因此两次握手建立连接是不安全的。
问题:为什么需要需要四次呢?
在关闭连接时,当服务端收到客户端发送的FIN包时,并不会立即关闭SOCKET,所以先回复一个ACK,告诉客户端已经收到客户端发的FIN包,只有等服务端所有数据都发送完毕后,服务端才会给客户端发送一个FIN包,在收到客户端回复的ACK后才能关闭连接,因此是四次。
问题:TIME_WAIT状态的作用,以及为什么要等待2MSL?
假设没有TIME_WAIT状态,主动关闭方直接进入CLOSED,如果这时立即重启客户端使用相同端口,再最后一次ACK丢失时,服务端重发FIN请求,就会被新客户端接受到;或者新客户端向服务端发起请求时,因为服务端正在等待最后一次ACK,因此新连接请求发送的SYN会被认为请求码错误,回复RST重置连接。因此需要主动关闭方发送最后一次ACK之后要进入一个TIME_WAIT状态等待一段时间,等待这段时间就是为了若接收到了重发的FIN请求能够进行最后一次ACK回复。
所谓的2MSL是两倍的最大报文生命周期,能够让网络中延迟的FIN/ACK数据都消失在网络里,不会对后续的连接造成影响。
问题:如果已经建立连接,但是客户端突然出现了故障会怎么办?
TCP还设有一个保活机制。显然,如果客户端出现了故障,服务端不能一直等下去。若等了一段时间还没有收到客户端的任何数据,服务端就会发送一个探测报文段,若一连发送10个探测报文段仍然没有反应,服务端就认为是客户端出现了故障,就会关闭连接。