四次挥手断开连接
四次挥手是TCP连接释放的过程,在挥手开始之前,主动关闭方结束ESTABLISHED状态,然后开始四次挥手
1.首先主动关闭方发送FIN给被动关闭方,然后主动关闭方进入FIN_WAIT1状态即半关闭状态,并且停止向被动关闭方发送数据
2.被动关闭方收到FIN后,结束ESTABLISHED状态,回复ACK给主动关闭方,然后进入CLOSE_WAIT状态
3.主动关闭方收到ACK后,确认被动关闭方已经收到了连接释放请求,然后主动关闭进入FIN_WAIT2状态
4.被动关闭方发出ACK后,将遗留的待传数据传送完毕,做好释放连接的准备后,向主动关闭方发送FIN,然后进入LAST_ACK状态,并且停止向主动关闭方发送数据;
5.主动关闭方收到FIN,确认被动关闭方已经做好释放连接的准备,向被动关闭方发送ACK,然后进入TIME_WAIT状态
6.被动关闭方收到ACK后,然后进入CLOSED状态
6.主动关闭方在TIME_WAIT状态等待2MSL后,然后进入CLOSED状态,
完成四次挥手;
挥手为什么是四次?
TCP断开连接需要四次挥手是因为ACK和FIN是分别在两次挥手中传输的,
主动关闭方在数据传输完毕后发送FIN,而被动关闭方可能还有数据要传输,因此不会将FIN一起发送而是先回复ACK,等被动关闭方数据传输完毕后,再发送FIN
TIME_WAIT状态的作用?
主动关闭方向被动关闭方发送最后一次ACK后进入的状态,目的是为了等待两个MSL(报文最大生存周期)时间;
如果没有TIME_WAIT,主动关闭方收到FIN后就关闭连接,而被动关闭方相应的端口并没有关闭,如果主动关闭方在相同的端口立即建立新的连接,则有可能收到上一次连接中残留的数据包,导致异常;
除此之外,如果主动关闭方最后一次发送的ACK丢包了,由于TCP的超时重传机制,被动关闭方将重发FIN,如果主动关闭方没有TIME_WAIT直接关闭的话,当收到被动关闭方重发的FIN包时,主动关闭方就会发送RST包给被动关闭方,使得对方认为有错误发生,但是并没有异常情况发生;
TIME_WAIT为什么是2MSL?
主动关闭方发送最后一次ACK后并不能保证被动关闭方一定能接收到该段报文,所以主动关闭方发送完ACK后,会设置一个时长为2MSL的计时器,MSL是指一段TCP报文在传输过程中的最大生命周期, 2MSL是被动关闭方发出FIN和主动关闭方发出ACK报文所能保持有效的最大时长。
如果被动关闭方在1MSL内没有收到主动关闭方的ACK报文,再次向主动关闭方发送FIN报文,如果主动关闭方在2MSL内收到了被动关闭方的FIN报文,说明ACK丢包了,主动关闭方将对ACK进行重传,并重新开始2MSL的计时
如果主动关闭方在2MSL内没有收到被动关闭方的FIN报文,说明被动关闭方正常接收ACK,主动关闭方进入CLOSED状态,完成四次挥手
2MSL的时长是为了确认被动关闭方收到ACK报文
CLOSED_WAIT状态的作用?
CLOSED_WAIT是被动关闭方收到FIN回复ACK后进入的状态,目的是保证被动关闭方在连接关闭之前将没有发送的数据发送完毕;
一台主机上出现大量TIME_WAIT的原因?解决方案?
TIME_WAIT是主动关闭方收到FIN进行最后一次ACK回复后进入的状态;
TIME_WAIT过多是因为大量主动关闭套接字,常见于爬虫服务器创建大量客户端请求然后关闭;
解决方案:
设置套接字选项使用地址重用,服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口被占用,但TCP连接位于TIME_WAIT状态时可以重用端口;
一台主机上出现大量CLOSE_WAIT的原因?解决方案?
CLOSE_WAIT是被动关闭方收到FIN进行ACK回复后进入的状态,接下来发送FIN之后就会进入LAST_ACK;
解决方案:
一直处于CLOSE_WAIT说明代码中对于断开连接的套接字没有关闭,检查代码;
调整系统参数,包括句柄相关参数和TCP/IP参数,一般一个CLOSE_WAIT会维持至少2个小时的时间,可以调整参数来缩短这个时间;