2014-02-10 16 views
1

我正在用C编写一个基于epoll的网络服务器。当我创建我的套接字来监听传入连接时,我使用fcntl使它成为非阻塞。同样,当来自客户端的传入连接到达时,我会在对它们做任何事情之前使它们的套接字非阻塞,并且对于传出连接的套接字也是如此。获取SIGPIPE与非阻塞套接字 - 这是正常的?

有时我的服务器得到一个SIGPIPE - 我认为这是当我尝试写入客户端已关闭的客户端连接。这对我来说似乎很陌生;我认为,用非阻塞套接字而不是SIGPIPE,我应该从呼叫回writeECONNRESETerrno-1

有什么我失踪了吗?或者,即使使用非阻塞套接字(也就是说,我应该明确地忽略在我的设置中使用signal(SIGPIPE, SIG_IGN))的信号,同时获得SIGPIPE和错误代码是正常的吗?

回答

2

是的,这是正常的。如果您向另一端关闭连接的套接字(非阻塞)写入数据,您将得到一个SIGPIPE或(如果您阻止了SIGPIPE信号)返回一个错误(-1),其中errno设置为EPIPE

从手册页write

EPIPEfd连接到管道或插座,其读出端是封闭的。发生这种情况时,写入过程也将收到 a SIGPIPE信号。 (由此,写返回值被认为是只有当程序捕获,块或忽略该信号。)

POSIX标准是在这里:http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html并说:

[EPIPE]尝试到由写入一个管道或FIFO,这个管道或FIFO不能通过任何进程读取,或只有一端打开。一个SIGPIPE信号也将被发送到该线程。

+0

谢谢!不知道我是如何设法错过的。我将添加SIG_IGN处理程序。我会得到ECONNRESET吗?或者,对于别的东西,我只需要寻找EPIPE? –

+1

POSIX标准(但不是Linux手册页)说,如果套接字从来没有连接过,你会得到'ECONNRESET'。假设你专门处理'EINTR','EAGAIN'和'EWOULDBLOCK',那么通常我会将其他任何错误情况视为致命错误并假定连接已经死亡。 – abligh

+0

非常好,非常感谢。我会这样做。 –

1

SIGPIPE是正常的。除了仅为此目的设置信号处理器之外,另一个选项是每当发送时都使用标志MSG_NOSIGNAL。