【发布时间】:2011-08-04 03:39:02
【问题描述】:
谁能提供一个示例,说明如何使用 select() 查看客户端是否关闭了套接字上的连接?
仅供参考。我用的是linux。
谢谢!
【问题讨论】:
-
当连接被另一端关闭时,read 返回 0。
谁能提供一个示例,说明如何使用 select() 查看客户端是否关闭了套接字上的连接?
仅供参考。我用的是linux。
谢谢!
【问题讨论】:
下面的 sn-p 首先检查套接字是否标记为可读(关闭时标记为可读),然后检查是否实际上有任何内容要读取。
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>
bool isclosed(int sock) {
fd_set rfd;
FD_ZERO(&rfd);
FD_SET(sock, &rfd);
timeval tv = { 0 };
select(sock+1, &rfd, 0, 0, &tv);
if (!FD_ISSET(sock, &rfd))
return false;
int n = 0;
ioctl(sock, FIONREAD, &n);
return n == 0;
}
【讨论】:
MSG_PEEK 标志的recv() 可以在一行中完成。
recv() 不是this 问题的答案,而是解决不同问题的方法。
您无需在select() 后面跟着ioctl()。您可以改为对套接字进行非阻塞窥视,看看它是否返回 0。
bool isclosed (int sock) {
char x;
interrupted:
ssize_t r = ::recv(sock, &x, 1, MSG_DONTWAIT|MSG_PEEK);
if (r < 0) {
switch (errno) {
case EINTR: goto interrupted;
case EAGAIN: break; /* empty rx queue */
case ETIMEDOUT: break; /* recv timeout */
case ENOTCONN: break; /* not connected yet */
default: throw(errno);
}
}
return r == 0;
}
【讨论】:
如果您收到读取通知并且读取返回 0 字节,则客户端已完全退出。如果没有,您将收到异常通知。
【讨论】: