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

发布于 2024-11-01 01:03:11 字数 90 浏览 0 评论 0原文

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

供参考。我正在使用Linux。

谢谢!

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

FYI. I'm using linux.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜警司 2024-11-08 01:03:11

下面的代码片段首先检查套接字是否标记为可读(关闭时为可读),然后检查是否确实有任何内容可供读取。

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

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;
}
不气馁 2024-11-08 01:03:11

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

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.

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;
}
懒猫 2024-11-08 01:03:11

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

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.

思念绕指尖 2024-11-08 01:03:11

下面是一个示例,用于检查套接字是否被对等方关闭,而无需在接收缓冲区非空的情况下读取套接字。

#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* FOR: POLLRDHUP define */
#endif
#include <poll.h>

bool connection_peer_closed(int fd)
{
    struct pollfd pfd;
    int ret;

    if (fd < 0) {
        return true;
    }

    pfd.fd = fd;
    pfd.events = POLLRDHUP;
    pfd.revents = 0;
    ret = poll(&pfd, 1, 0);
    if (ret > 0 && (pfd.revents & (POLLHUP | POLLERR | POLLRDHUP))) {
        return true;
    } else {
        return false;
    }
}

Here is an example to checks if the socket is closed by peer WITHOUT reading form it in case of non-empty recv buffer.

#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* FOR: POLLRDHUP define */
#endif
#include <poll.h>

bool connection_peer_closed(int fd)
{
    struct pollfd pfd;
    int ret;

    if (fd < 0) {
        return true;
    }

    pfd.fd = fd;
    pfd.events = POLLRDHUP;
    pfd.revents = 0;
    ret = poll(&pfd, 1, 0);
    if (ret > 0 && (pfd.revents & (POLLHUP | POLLERR | POLLRDHUP))) {
        return true;
    } else {
        return false;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文