【问题标题】:SIGPIPE (OSX) and disconnected sockets?SIGPIPE(OSX)和断开连接的套接字?
【发布时间】:2013-10-30 19:41:23
【问题描述】:

我正在开发一个通过 TCP 连接到服务器的应用程序。

如果套接字由于某种原因被关闭,我最终会进入 SIGPIPE 处理程序。

我该怎么做才能使 recv 和 send 只在断开/关闭的套接字上返回错误?

谢谢

【问题讨论】:

标签: c xcode macos sockets sigpipe


【解决方案1】:

SIG_IGN 信号而不是处理它。 send 将返回 -1 并且 errno 将设置为 EPIPE。

【讨论】:

  • recv 呢?这 --> signal(SIGPIPE, SIG_IGN) 似乎没有帮助。我仍然得到一个 SIGPIPE。我猜 recv 只是阻塞,直到套接字关闭?如果连接因某种原因断开,recv 将返回什么?只有 0 个?
  • read()recv() 返回 0 如果对等方关闭或关闭连接。有关详细信息,请参阅 man readman recv。如果仍然不清楚,请就这个不同的主题提出另一个问题。
  • 正如alk所说,您不必担心带有recv的sigpipe。如果套接字对等体关闭,您将收到零读取的正常关闭通知。 signal 系统调用语义跨平台是非标准的。在 linux 上,您可以通过功能测试宏来哄它按照您想要的方式运行,但我不知道 OSX 的默认设置。最好使用sigaction,我看到alk 留下了一个描述如何做到这一点的答案。
【解决方案2】:

使用信号处理程序或忽略它

#include <signal.h>
signal(SIGPIPE, SIG_IGN);

在写入套接字时,首先检查套接字 fd 是否为正或不在程序中。在外部,您应该检查您是否正在发送有效套接字的指针

【讨论】:

  • 你使用#include 了吗??
  • @user1884325:如果使用signal(),您很可能需要在使用一次后重新应用处理程序。不要使用signal使用sigaction()`。
  • 是的 sigaction 更具描述性和更有用,但 POSIX.1 和信号是基本的,但它是 ISO C 的一个特性
【解决方案3】:

你可以忽略SIGPIPE

 #include <signal.h>

signal(SIGPIPE, SIG_IGN);

或者您可以使用信号处理程序。

signal(SIGPIPE, handler);
void handler(int signal)
{   
    //("Signal caught");

}

【讨论】:

  • 不要在信号处理程序中使用printf(),因为不能保证printf() 是信号安全的。
  • @alk 谢谢。已更新。
【解决方案4】:

要忽略信号,请将信号处理程序设置为 SIG_IGN 这样做:

struct sigaction sa;
memset(&sa, 0, sizeof(sa));

sa.sa_handler = SIG_IGN;

if (-1 == sigaction(SIGPIPE, &sa, NULL))
{
  perror("sigaction() failed");
}

【讨论】:

    【解决方案5】:

    我发现忽略 SIGPIPE 在 OS X 上无效。请改用 SO_NOSIGPIPE。请注意,这是在套接字上设置一次,而不是在每次调用 send() 时请求的 MSG_NOSIGNAL。

    int socket = accept (...); /* (or however you're getting the socket) */
    int option_value = 1; /* Set NOSIGPIPE to ON */
    if (setsockopt (socket, SOL_SOCKET, SO_NOSIGPIPE, &option_value, sizeof (option_value)) < 0) {
        perror ("setsockopt(,,SO_NOSIGPIPE)");
    }
    

    【讨论】:

      【解决方案6】:

      忽略 SIGPIPE,如其他答案中所述(即signal(SIGPIPE, SIG_IGN);)在 OS X 上对我有用。另外,请务必在调试器之外进行测试,如this comment 中所述。我正在使用lldb 进行调试,它的信号处理正在使用 SIGPIPE 终止我的程序,即使我忽略了该信号。在lldb 之外的测试工作正常。

      【讨论】:

        猜你喜欢
        • 2011-01-02
        • 2021-12-09
        • 2019-03-05
        • 1970-01-01
        • 1970-01-01
        • 2012-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多