SIGPIPE问题分析

问题描述:

  Linux下应用软件崩溃,报SIGPIPE错误。跟踪代码发现服务端关闭socket连接后,客户端继续向服务端发送报文导致。(ps:对于老手,定位问题应该更快,通过SIGPIPE就能判断错误位置,可以参考linux下错误提示errrno,可以看手册man,也可以参考博主https://blog.csdn.net/u010629326/article/details/76021420)。

问题分析:

  SIGPIPE错误的原因就是服务端Socket关闭,客户端继续向服务端发送报文导致的错误。

问题解决:

  由上面原因总结出两种方法:

1、设置系统忽略SIGPIPIE消息,从结果解决SIGPIPE错误导致程序崩溃问题;

在socket建立时设置下列属性,socket将不会产生SIGPIPE信号。

int optval=1;

#ifdef __linux__ 

    setsockopt(m_Sockfd, SOL_SOCKET, MSG_NOSIGNAL, &optval, sizeof(optval));

#else  

    setsockopt(m_Sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));

#endif

在main函数设置如下属性,SIGPIPE信号还是会产生,只是应用程序不将处理这个信号,也就不会闪退。

#ifdef UNIX_ENV

    struct sigaction sa;

    sa.sa_handler = SIG_IGN;

    sigaction(SIGALRM, &sa, 0);

    sigaction(SIGPIPE, &sa, 0);

#endif

2、客户端在发送报文前判断连接状态,并决定是否重新建立连接,这样从根源解决这个问题。

    客户端在发送前非阻塞读取数据,如果发现recv()返回0时,代表服务端已经关闭socket,此时需要重新建立连接。为了方便调试,linux下返回错误提示的变量errno可以输出出来查看,此变量在socket建立时初始值为0,非组态connect连上后值为errno值发生变化一般为EINPROGRESS。

    当调用connect、listen、accept、recv、write等socket接口时,返回小于0的值时表示出现错误,可以通过查看errno值定位问题。目前看来其他返回值不会修改errno的值。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值