2010-11-12 41 views
7

在客户端,我有一个为什么我写的这个服务器检测不到客户端已经关闭了它的套接字?

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是一个结构的pollfd和sockfd.fd是客户端的套接字的文件描述符。

当客户端像我放在那里关闭套接字时,服务器似乎没有用第二个代码(desc_set [i] .revents & POLLHUP等)检测到它。

有谁知道有什么问题?

回答

9

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

POLLHUP,POLLERRPOLLNVAL只检查本地连接的输出端,这里仍然有效。有一个POLLRDHUP,这是一个GNU扩展,应该检测到对方关闭,但是你正在做的测试只是检查它是否仍然可写,而不是它是否仍然可读。

另请参见this question,这是谈论java,但仍然非常相关。

+0

对不起,我们要如何将这个GNU扩展插入到我的代码中? – dasen 2010-11-12 16:05:19

+0

#define _GNU_SOURCE在任何#includes之前都会这样做。使它自己的免费服务器调用close()一旦被服务请求是一个更好,更好的方法。 – Flexo 2010-11-12 16:07:12

+0

我已经使用了GNU扩展,但它仍然没有在服务器端关闭。 – dasen 2010-11-12 16:11:11

4

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

顺便说一句,你上面的测试条件应该读取sockfd.revents &(POLLERR | POLLHUP | POLLNVAL)。

+0

右 - 一个优雅的'close()'通过'read()'返回0来发信号,所以它由'POLLIN'指示。 – caf 2010-11-16 05:42:25

相关问题