tcp四次挥手出现异常 (tcp四次挥手详细过程)

上一章节已经向大家详细地介绍过TCP协议,此处不过多赘述,详见学习笔记-TCP简单理解。

花式理解

和三次握手一样(学习笔记-TCP三次握手),首先我们依然来欣赏一段爱情故事,与三次握手不同的是,这次的爱情故事是悲惨的,老忧桑了。

自从上次牵手成功之后,李雷和韩梅梅就过上没羞没臊的幸福生活。然而好景不长,七年之痒就来了。某日黄昏,还是在教学楼后的那条小道上,两人四眼相对,就这样对视了很久,很久。而后韩梅梅率先打破了沉默:

1, 韩梅梅道:"分手吧(FIN),你连倒立洗头都不会(seq=x),怎么和我在一起。"

2, 李雷回道:"就因为我不会倒立洗头是吧(ack=x+1),好(ACK),我让你飞,伤痛我背。"

说完之后韩梅梅删光了李雷的所有联系方式,头也不回地走了。(此时处于半连接状态,李雷可以联系韩梅梅,而韩梅梅无法主动联系李雷。)

回到宿舍的李雷越想越气,这是什么扯淡的理由啊,心想,我不能输。于是主动联系了韩梅梅:

3, 李雷道:"分手就分手(FIN),我不会倒立洗头(ack=x+1),你会用手走路吗(seq=y)。"

4, 韩梅梅回道:"好(ACK),我不会用手走路(ack=y+1),所以不合适。"

说罢之后,李雷也删除了韩梅梅的所有联系方式,自此之后,两人彻底失去联系。从此劳燕分飞。

四次挥手流程

所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。整个流程如下图所示:

tcp3次握手四次挥手,tcp为什么要挥手四次

四次挥手流程图

(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。

(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。

(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

四次挥手拓展

上面是以客户端主动发起关闭请求为例。而实际上也有可能存存在另一种情况。

由于TCP连接是全双工的,因此,客服端和服务端均可以发起关闭请求。服务端发起的关闭请求与客户端发起的相似,不过多赘述。下面展示的是同时发起主动关闭的情况,具体流程如下图:

tcp3次握手四次挥手,tcp为什么要挥手四次

字段说明

CLOSED:表示初始状态。

LISTEN:表示服务器端的某个SOCKET处于,可以接受连接了。

SYN_RCVD:这个状态表示接受到了SYN,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。

SYN_SENT:这个状态与SYN_RCVD遥相呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。

ESTABLISHED:表示连接已经建立了。

FIN_WAIT_1:这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。

FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

TIME_WAIT:表示收到了对方的FIN,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

CLOSING:这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也就会出现CLOSING状态,表示双方都正在关闭SOCKET连接。(如上 四次挥手拓展 中展示)

CLOSE_WAIT:这种状态的含义其实是表示在等待关闭。当对方close一个SOCKET后发送FIN给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是查看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。

LAST_ACK:这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

本文的初衷为学习笔记的分享,部分图文来源于网络,如侵,联删。