远程主机终止后的recv()调用挂起 [英] Recv() call hangs after remote host terminates

查看:160
本文介绍了远程主机终止后的recv()调用挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是,我有一个线程处于的recv()调用。远程主机突然终止(不密切()套接字调用),而recv()调用继续阻止。这显然​​不是一件好事,因为当我加入线程关闭的进程(本地),这个线程将永远不会退出,因为它是在一个recv的,将永远不会等待。

My problem is that I have a thread that is in a recv() call. The remote host suddenly terminates (without a close() socket call) and the recv() call continues to block. This is obviously not good because when I am joining the threads to close the process (locally) this thread will never exit because it is waiting on a recv that will never come.

所以我的问题是用什么方法做的人普遍认为是解决这一问题的最好方法?还有值得注意的一些额外的事情,应该回答之前被称为:

So my question is what method do people generally consider to be the best way to deal with this issue? There are some additional things of note that should be known before answering:


  • 有没有办法让我以确保远程主机关闭,退出前插座。

  • There is no way for me to ensure that the remote host closes the socket prior to exit.

这解决方案不能使用外部库(如boost)。它必须使用C ++ / C(preferably不是C ++ 0x中特定的)的标准库/功能。

This solution cannot use external libraries (such as boost). It must use standard libraries/features of C++/C (preferably not C++0x specific).

我知道这很可能已经被要求在过去,但我还想得到某人需要为如何正确地解决此问题(没有做一些超级哈克,我会在过去所做的那样)。

I know this has likely been asked in the past but id like to get someones take as to how to correct this issue properly (without doing something super hacky which I would have done in the past).

谢谢!

推荐答案

假设你想继续使用阻止套接字,您可以使用的 SO_RCVTIMEO 套接字选项

Assuming you want to continue to use blocking sockets, you can use the SO_RCVTIMEO socket option:

   SO_RCVTIMEO and SO_SNDTIMEO
          Specify the receiving or sending  timeouts  until  reporting  an
          error.   The parameter is a struct timeval.  If an input or out-
          put function blocks for this period of time, and data  has  been
          sent  or received, the return value of that function will be the
          amount of data transferred; if no data has been transferred  and
          the  timeout has been reached then -1 is returned with errno set
          to EAGAIN or EWOULDBLOCK just as if the socket was specified  to
          be  nonblocking.   If  the  timeout is set to zero (the default)
          then the operation will never timeout.

所以,你开始接收前:

So, before you begin receiving:

struct timeval timeout = { timo_sec, timo_usec };
int r = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
assert(r == 0); /* or something more user friendly */

如果您愿意使用非阻塞I / O,那么你可以使用调查()选择()的epoll()的kqueue(),或任何适当的事件调度机制是为您的系统。你需要使用的原因非阻塞I / O是,你需要让系统调用的recv()返回来通知你,有在没有数据插座的输入队列。使用这个例子是多一点点的参与:

If you are willing to use non-blocking I/O, then you can use poll(), select(), epoll(), kqueue(), or whatever the appropriate event dispatching mechanism is for your system. The reason you need to use non-blocking I/O is that you need to allow the system call to recv() to return to notify you that there is no data in the socket's input queue. The example to use is a little bit more involved:

for (;;) {
    ssize_t bytes = recv(s, buf, sizeof(buf), MSG_DONTWAIT);
    if (bytes > 0) { /* ... */ continue; }
    if (bytes < 0) {
        if (errno == EWOULDBLOCK) {
            struct pollfd p = { s, POLLIN, 0 };
            int r = poll(&p, 1, timo_msec);
            if (r == 1) continue;
            if (r == 0) {
                /*...handle timeout */
                /* either continue or break, depending on policy */
            }
        }
        /* ...handle errors */
        break;
    }
    /* connection is closed */
    break;
}

这篇关于远程主机终止后的recv()调用挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆