Linux c ++如何使用select查看套接字是否已关闭

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5640144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:38:30  来源:igfitidea点击:

c++ how to use select to see if a socket has closed

c++linuxsocketsselect

提问by poy

Can someone provide me an example of how to use select() to see if a client has closed the connection on a socket?

有人可以为我提供一个如何使用 select() 来查看客户端是否关闭了套接字连接的示例吗?

FYI. I'm using linux.

供参考。我正在使用Linux。

Thanks!

谢谢!

采纳答案by Erik

The below snippet first checks if the socket is marked readable (which it is when closed) and then if there's actually anything to be read.

下面的代码片段首先检查套接字是否被标记为可读(关闭时是这样),然后检查是否真的有任何东西要读取。

#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;
}

回答by WebWeasel

If you get a read notification and the read returns 0 bytes the client has exited cleanly. If not you will get an exception notification.

如果您收到读取通知并且读取返回 0 字节,则客户端已正常退出。如果没有,您将收到异常通知。

回答by jxh

You don't need to do a select()followed by ioctl(). You can instead do a non-blocking peek on the socket to see if it returns 0.

您不需要执行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;
}