为什么我写的这个服务器没有检测到客户端已经关闭了它的套接字?
在客户端中,我有一个
close(sockfd)
sockfd ,其中 sockfd 是连接到服务器的套接字。 在服务器中,我得到了这个:
if (sockfd.revents & POLLERR ||
desc_set[i].revents & POLLHUP || desc_set[i].revents & POLLNVAL) {
close(sockfd.fd);
printf("Goodbye (connection closed)\n");
}
其中 sockfd 是一个 struct pollfd,而 sockfd.fd 是客户端套接字的文件描述符。
当客户端像我在那里那样关闭套接字时,服务器似乎没有使用第二个代码(desc_set[i].revents & POLLHUP 等)检测到它。
有谁知道有什么问题吗?
In the client, I have a
close(sockfd)
where sockfd is the socket that's connected to the server.
In the server I've got this:
if (sockfd.revents & POLLERR ||
desc_set[i].revents & POLLHUP || desc_set[i].revents & POLLNVAL) {
close(sockfd.fd);
printf("Goodbye (connection closed)\n");
}
Where sockfd is a struct pollfd, and sockfd.fd is the file descriptor of the client's socket.
When the client closes the socket like I put up there, the server doesn't seem to detect it with the second code (desc_set[i].revents & POLLHUP, etc.).
Does anyone know what's the problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
听起来您已经成功地从客户端半关闭连接。在这种状态下,连接仍然可以在一个方向上发送数据,即它以半双工模式运行。这是设计使然,将允许您的服务器完成对客户端发送的任何内容的回复。通常,这意味着完成文件传输并调用 close(),或回答查询的所有方面。 在半关闭状态下,您仍然可以相当明智地向已调用
close()
的一侧发送数据。如果您尝试阅读,在您的服务器中您将看到 eof。close()
只是意味着“我已完成发送,完成我要求的任何内容”。POLLHUP
、POLLERR
和POLLNVAL
只检查本地连接的输出端,在这里仍然有效。有一个 POLLRDHUP,它是一个 GNU 扩展,应该检测另一端关闭,但您所做的测试只是检查它是否仍然可写,而不是检查它是否仍然可读。另请参阅此问题,这是在谈论java,但仍然非常相关。
Sounds like you've managed to half close the connection from the client side. In this state the connection can still send data in one direction, i.e. it operates in half-duplex mode. This is by design and would allow your server to finish replying to whatever the client sent. Typically this would mean completing a file transfer and calling
close()
, or answering all of the aspects of the query. In the half-closed state you can still quite sensibly send data to the side that has already calledclose()
. In your server you will see eof if you try to read though.close()
just means "I'm done sending, finish up whatever I asked for".POLLHUP
,POLLERR
andPOLLNVAL
only checks the output side of the local connection, which is still valid here. There's aPOLLRDHUP
, which is a GNU extension that should detect the other side closing, but the tests you're doing are only checking if it's still writable, not if it's still readable.See also this question, which is talking about java, but still very related.
远程关闭或输出关闭既不是错误,也不是挂起,也不是无效状态。这是一个读取事件,read() 将返回零。只需将其作为正常读取处理的一部分来处理即可。
顺便说一句,您上面的测试条件应阅读 sockfd.revents & (POLLERR|POLLHUP|POLLNVAL)。
A remote close or output shutdown is neither an error nor a hangup nor an invalid state. It is a read event such that read() will return zero. Just handle it as part of your normal read processing.
BTW your test condition above should read sockfd.revents & (POLLERR|POLLHUP|POLLNVAL).