gpt4 book ai didi

c++ - Recv() 调用在远程主机终止后挂起

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:27:50 27 4
gpt4 key购买 nike

我的问题是我有一个正在调用 recv() 的线程。远程主机突然终止(没有 close() 套接字调用)并且 recv() 调用继续阻塞。这显然不好,因为当我加入线程以关闭进程(本地)时,该线程将永远不会退出,因为它正在等待永远不会到来的 recv。

所以我的问题是人们通常认为哪种方法是处理此问题的最佳方法?在回答之前还应了解一些其他注意事项:

  • 我无法确保远程主机在退出之前关闭套接字。

  • 此解决方案不能使用外部库(例如 boost)。它必须使用 C++/C 的标准库/功能(最好不是特定于 C++0x 的)。

我知道过去可能有人问过这个问题,但我想让别人知道如何正确地纠正这个问题(而不是做一些我过去会做的 super 骇人听闻的事情)。

谢谢!

最佳答案

假设你想继续使用阻塞套接字,你可以使用 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.

因此,在您开始接收之前:

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,那么你可以使用poll(), select(), epoll()kqueue() 或适用于您的系统的任何适当的事件调度机制。您需要使用非阻塞 I/O 的原因是您需要允许对 recv() 的系统调用返回以通知您套接字的输入队列中没有数据。要使用的示例涉及更多:

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

关于c++ - Recv() 调用在远程主机终止后挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17226876/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com