和三次握手一样(学习笔记-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来触发。整个流程如下图所示:
(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连接是全双工的,因此,客服端和服务端均可以发起关闭请求。服务端发起的关闭请求与客户端发起的相似,不过多赘述。下面展示的是同时发起主动关闭的情况,具体流程如下图:
字段说明
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可用状态了。
还没有评论,来说两句吧...