TCP协议的学习(四)TCP四次挥手及解释

发起断开连接请求可以是客户端也可以是服务器,即主机1,主机2可以是客户端也可以是服务器。
ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1。
FIN (finis)即完,终结的意思, 用来释放一个连接。当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。
发送序列号:Sequence Number
确认序列号:Acknowledgment Number

FIN_WAIT_1:表示等待对方的FIN报文。当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET进入到FIN_WAIT_1 状态
FIN_WAIT_2:也表示等待对方的FIN报文。FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。你回复一个ACK给对方,并进入CLOSE_WAIT状态。接下来就是查看你是否还有数据要发送给对方,如果没有,就可以close这个socket,并发送FIN给对方,即关闭连接。
CLOSING:表示主机1给主机2发送FIN后,并没有收到主机2回应的ACK,而收到了主机2发送的FIN。表示双方同时close一个socket,出现同时发送FIN现象。
LAST_ACK: 发送FIN报文后,等待对方的ACK报文,当收到ACK报文后,进入到CLOSED状态。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK确认,等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态。

这里写图片描述

第一次挥手:主机1向主机2,发送FIN报文段,表示关闭数据传送,并主机1进入FIN_WAIT_1状态,表示没有数据要传输了
第二次挥手:主机2收到FIN报文段后进入CLOSE_WAIT状态(被动关闭),然后发送ACK确认,表示同意你关闭请求了,主机到主机的数据链路关闭,主机进入FIN_WAIT_2状态
第三次挥手:主机2等待主机1发送完数据,发送FIN到主机1请求关闭,主机2进入LAST_ACK状态
第四次挥手:主机1收到主机2发送的FIN后,回复ACK确认到主机2,主机1进入TIME_WAIT状态。主机2收到主机1的ACK后就关闭连接了,状态为CLOSED。主机1等待2MSL,仍然没有收到主机2的回复,说明主机2已经正常关闭了,主机1关闭连接。

孤儿连接
连续停留在FIN_WAIT2状态可能发生,客户端执行半关闭状态后,未等服务器关闭连接就直接退出了,此时客户端连接由内核接管。Linux为防止孤儿连接长时间存在内核中,定义了两个变量指定孤儿连接数目和生存时间。

为什么要四次挥手而不是三次呢?
当主机2发送ACK确认主机1的FIN时,并不代表主机2的数据发送完毕,主机1发送完FIN处于半关闭状态(不能发送数据,但可以接收数据),所以要等待主机2的数据发送完毕后,发出FIN关闭连接请求时,主机2才进入CLOSED状态,主机1再ACK确认关闭进入CLOSE状态。

为什么TIME_WAIT 状态要等2MSL才进入CLOSED状态?
MSL(Maximum Segment Lifetime):报文最大生存时间,是任何报文段被丢弃前在网络内的最长时间。当主机1回复主机2的FIN后,等待(2-4分钟),即使两端的应用程序结束。

如果主机1直接进入CLOSED状态,由于IP协议不可靠性或网络问题,导致主机1最后发出的ACK报文未被主机2接收到,那么主机2在超时后继续向主机1重新发送FIN,而主机1已经关闭,那么找不到向主机1发送FIN的连接,主机2这时收到RST并把错误报告给高层,不符合TCP协议的可靠性特点。
如果主机1直接进入CLOSED状态,而主机2还有数据滞留在网络中,当有一个新连接的端口和原来主机2的相同,那么当原来滞留的数据到达后,主机1认为这些数据是新连接的。等待2MSL确保本次连接所有数据消失。

TIME_WAIT状态过多会占用大量的端口号,处理方法:
修改内核参数
尽可能被动关闭连接
将长连接改为短连接

close和shutdown
只要TCP栈的读缓冲里还有未读取(read)数据,则调用close时会直接向对端发送RST
close把描述字的引用计数减1,仅在该计数变为0的时候才关闭套接口。而使用shutdown可以不管引用计数的值是多少都能激发TCP的正常连接终止序列,即发送FIN。
close终止数据传送的两个方向读和写。
shutdown函数进行关闭某一方向的操作。比如,有时我们只是需要告诉对方数据发送完毕,只需要关闭数据发送的一个通道,但还是要接受对方发过来的数据。

猜你喜欢

转载自blog.csdn.net/qq_34501940/article/details/51119726