为什么我写的这个服务器没有检测到客户端已关闭套接字呢?

时间:2010-11-12 15:51:51

标签: c sockets networking

在客户端,我有一个

close(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等)检测它。

有谁知道这是什么问题?

2 个答案:

答案 0 :(得分:10)

听起来你已经设法half close来自客户端的连接。在这种状态下,连接仍然可以在一个方向上发送数据,即它以半双工模式工作。这是设计使并且允许您的服务器完成对客户端发送的任何内容的回复。通常,这意味着完成文件传输并调用close(),或者回答查询的所有方面。 在半关闭状态下,您仍可以非常明智地将数据发送到已调用close() 的一侧。在您的服务器中,如果您尝试阅读,您将看到eof。 close()只是意味着“我已经完成了发送,完成了我要求的任何事情”。

POLLHUPPOLLERRPOLLNVAL仅检查本地连接的输出端,此处仍然有效。有一个POLLRDHUP,它是一个GNU扩展,可以检测到另一边关闭,但你正在做的测试只是检查它是否仍然是可写的,而不是它仍然可读。

另请参阅this question,它正在讨论java,但仍然非常相关。

答案 1 :(得分:4)

远程关闭或输出关闭既不是错误也不是挂起,也不是无效状态。这是一个read事件,read()将返回零。只需将其作为正常读取处理的一部分进行处理。

BTW你的测试条件应该是sockfd.revents& (POLLERR | POLLHUP | POLLNVAL)