33.TCP异常之服务器中断

当服务器通过ctrl+c中断TCP连接时,客户端在发送数据时会收到RST报文,导致阻塞。问题在于服务端未等待FIN报文就关闭,客户端忽略SIGPIPE信号。解决方案包括捕获SIGPIPE信号、使用I/O复用函数或异步I/O避免阻塞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在前面TCP套接字通信中有一个关于服务端关闭但是客户端没有断开的问题, 虽然这个问题已经得到解决了, 而且也分析过了, 但是本节还是想继续以问题为例来分析异常.


问题重现

这个问题的重现可以使用TCP套接字之通信中的代码, 也可以用TCP套接字之SIGCHLD中的代码. 这里我就使用后者.

服务端完整代码 : service.c

服务端运行 :

./a.out 1 8080 192.168.1.16

客服端完整代码 : client.c

客户端运行 :

./a.out 2 8080 192.168.1.16

在这里插入图片描述

现将服务端ctrl+c中断, 然后客户端接收到了FIN并且立马回了ACK确认报文, 但是客户端还处于阻塞并且发送数据时, 收到的确实对端的RST报文. 但是客户端收到RST后还是继续阻塞.

在这里插入图片描述


问题分析

正常的挥手过程中, 主动关闭方在收到ACK确认报文后进入FIN-WAIT2, 这个阶段没有收到对端的FIN理论上还可以接收数据只是不能发送了. 上面问题就在这里.

  1. 因为服务端立马就被杀死了, 原本应该等到FIN后才关闭, 但是对端还要等待终端输入数据才能送过去; 终端等待时间太长, 服务端等不了就直接被迫关闭进入TIME_WAIT阶段. 所以客户端很久在发送数据过来, 而对端已经关闭, 所以根本不认识这个连接直接回了RST.
  2. 对端第一次收到了RST之后还是没有退出, 因为此时循环又回到write函数, 被阻塞. 内核向进程发送了SIGPIPE信号, 希望终止客服端但是客户端默认忽略了该信号继续阻塞直到不阻塞后退出, 这就是还要输入第二次的原因.

解决问题

问题就出现在write函数阻塞, 进程忽略SIGPIPE信号. 方法有多种

  1. 捕捉SIGPIPE信号, 但是还是会被阻塞, 现象和之前一样, 但是我们至少捕捉到了.
  2. 采用select, poll, epoll等I/O复用函数
  3. 采用异步I/O

总结

虽然本节与前面的部分地方是重复的, 但是本节是从异常的方面分析该问题的, 侧重点不太一样.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值