TCP连接的关闭过程

本文讲述关于TCP连接关闭的系统状态、系统调用、报文。

客户端一般是主动关闭方,直接在程序在调用close()函数发出关闭请求(发送Fin报文)。

服务器端一般是关闭被动方,不会主动调用close()函数。

TCP连接关闭阶段的状态

当TCP其中一方调用close()函数之后,TCP连接进入四次挥手阶段。

FIN_WAIT_1
连接中断主动方的状态。
调用close()函数,发出连接中断请求FIN报文后进入该状态,等待对方的响应。

FIN_WAIT_2
连接中断主动方的状态。
收到了对方的中断请求ACK报文后进入该状态,等待对方的FIN报文。

TIME_WAIT
连接中断主动方的状态。
收到了对方的FIN报文,进入该状态,并发回最后一个ACK报文。然后等待一段时间(2倍的MSL),确保对方已收到该报文。

CLOSE_WAIT
连接中断被动方的状态。
收到对方的FIN报文后进入该状态,随后发出其最后需要发送的数据。

LAST_ACK
连接中断被动方的状态。
发送完最后需要发送的数据后,最后发送FIN报文,进入该状态,等待对方最后一个ACK报文。

CLOSED
连接中断被动方的状态。
收到对方最后一条ACK后,进入该状态。


关闭主动方的time_wait状态

关闭主动方最后会进入time_wait状态,这一状态会持续2msl。这么做的目的,一是确保对方收到了最后的ack报文;另一方面确保旧连接的报文经过这一时间段后全部作废。


四次挥手可以是三次

这种情况是:关闭被动方最后没有要发的数据了。于是直接把ack报文和fin报文合为一个报文发出。这样关闭主动方收到后,直接从fin_wait1状态变为time_wait状态(跳过了fin_wait2状态)。


连接的半关闭

关闭主动方调用shutdown函数,可以控制将本端的TCP连接的读或写关闭。
int shutdown(int sockfd,int how);
具体关闭方式由参数2来控制。
SHUT_RD :只写不读,接收到的数据会丢弃,不发送fin报文。
SHUT_WR :只读不写,输出缓冲区的数据会丢弃,要发送fin报文。
SHUT_RDWR :相当于调用shutdown两次:首先是以SHUT_RD,然后以SHUT_WR。

shutdown和close的区别:
如果多个进程共享一个套接字,close函数调用一次,套接字的计数引用减去1,为0时才关闭套接字,否则不会关闭套接字。
而shutdown不管引用计数。


进程如何关闭TCP连接?

1、对于客户端来说,一般调用close()来主动关闭连接。即使进程的代码中不调用close()函数,在进程终止时内核会自动关闭所有打开的描述符。

2、对于服务器来说,往往是TCP连接的被动方,不会主动调用close,那么进程需要能及时的感知到套接字的关闭。一般的,当服务器端发现与客户端通信的描述符不可读(读到了fin报文中的文件结束符eof)时,就认为连接关闭,这时候应用层,也就是服务器程序,把最后要发的数据发完,然后主动调用close()关闭这个描述符。

TCP连接的异常关闭

a、b两个正常连接的对端进程。假如b进程没有调用close就异常终止,那么发送FIN包是内核OS代劳,b进程已经不存在,当内核再次收到该socket的消息时,会回应RST报文(因为拥有该socket的进程已经终止)。a进程对收到RST的socket调用write时,内核会给a进程发送SIGPIPE,该信号默认情况下会终止当前a进程。 

注意不管是怎么样描述符是如何被关闭的,都会使内核向描述符的对端发送FIN报文。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCP连接过程可以分为三个阶段:建立连接、数据传输、关闭连接。 1. 建立连接阶段: 在建立TCP连接之前,客户端和服务器必须首先要建立一个三次握手的过程,以确保彼此之间的通信是可靠的。 1)客户端发送一个SYN(同步)包到服务器,表示客户端要发起连接,并告诉服务器客户端的初始序列号。 2)服务器收到SYN包后,回应一个SYN+ACK(同步确认)包给客户端,表示服务器收到了客户端的SYN包,并且告诉客户端服务器的初始序列号。 3)客户端收到SYN+ACK包后,发送一个ACK(确认)包给服务器,告诉服务器客户端收到了服务器的SYN+ACK包,并且客户端和服务器之间的连接已经建立。 2. 数据传输阶段: 在TCP连接建立之后,客户端和服务器之间可以开始进行数据传输。数据传输通常是通过分段的方式进行的,每个数据包都包含了序列号和确认号,以确保数据包的可靠传输。 3. 关闭连接阶段: 当客户端或服务器需要关闭连接时,需要进行四次挥手的过程。 1)客户端发送一个FIN(结束)包给服务器,告诉服务器客户端已经完成了数据发送。 2)服务器收到FIN包后,回应一个ACK包给客户端,告诉客户端服务器已经收到了客户端的FIN包。 3)服务器发送一个FIN包给客户端,告诉客户端服务器已经完成了数据发送。 4)客户端收到服务器的FIN包后,回应一个ACK包给服务器,告诉服务器客户端已经收到了服务器的FIN包,并且客户端已经关闭连接。 这样四次挥手的过程可以保证客户端和服务器之间的连接关闭是可靠的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值