如何检测socket是否关闭,socket的关闭检测及处理

socket的关闭检测及处理

检测socket关闭
reference SIGPIPE 信号处理整理

调用write, send, sendto等发送函数时,触发 SIGPIPE 信号,导致程序直接退出。

Program received signal SIGPIPE, Broken pipe.
0x00007ffff7af2224 in write () from /lib/x86_64-linux-gnu/libc.so.6

程序将 errno 设置为 EPIPE 之后,程序接受到内核发送过来的 SIGPIPE 信号退出。

产生 SIGPIPE 的条件:

  1. 对一个已经收到 FIN 包的 socket 调用 read 方法,如果接收缓冲已空,则返回 0,这就是常说的“连接关闭”表示。

  2. 对一个已经收到 FIN 包的 socket 第一次调用 write 方法时,如果发送缓冲没问题,则 write 调用会返回写入的数据量,同时进行数据发送。但是发送出去的报文会导致对端发回 RST 报文。因为对端的 socket 已经调用了 close 进行了完全关闭,已经处于既不发送,也不接收数据的状态。所以第二次调用 write 方法时(假设在收到 RST 之后)会生成 SIGPIPE 信号,导致进程退出(这就是为什么第二次 write 才能触发 SIGPIPE 的原因)。 <----- 这个应该是阻塞socket才这样,没有试验过

处理SIGPIPE How to prevent SIGPIPEs (or handle them properly)

  1. 设置信号处理函数

    signal(SIGPIPE, SIG_IGN);

  2. 设置socket option,忽略SIGPIPE信号,转为处理对应的errno,这样就不用安装信号处理函数

    int set = 1;
    setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
    

注意:在Linux中没有SO_NOSIGPIPE信号: SO_NOSIGPIPE was not declared,但是我们可以在调用send或者recv的信号带上MSG_NOSIGNAL

send(fd, buf, nBytes, MSG_NOSIGNAL);

服务端关闭socket

做了如下测试,如下代码是客户端代码片段,服务端用nc监听一个端口作为服务端

sleep(10);
char buf[32];
ret = recv(event[i].data.fd, buf, 32, MSG_NOSIGNAL);
LOG_DEBUG("recv ret: %d, errno: %d, error: %s", ret, errno, strerror(errno));
ret = send(event[i].d
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值