在另一个线程上接收的套接字上触发 EAGAIN

Posted

技术标签:

【中文标题】在另一个线程上接收的套接字上触发 EAGAIN【英文标题】:Trigger an EAGAIN on a socket receiving on another thread 【发布时间】:2015-09-15 12:50:55 【问题描述】:

假设我有两个线程,主线程和一个专用于连续侦听标准 TCP 套接字的线程。现在,说在某个时候我想关闭所有东西。从主线程,我想关闭监听线程正在处理的连接,然后加入线程并结束程序。

但是,这很棘手,因为我不知道如何使侦听线程从对read 的调用中返回。除非实际收到某些内容,否则该调用不会返回,原则上我可能会等待很长时间,直到另一个端点决定向我发送某些内容。

当我使用 UDP 套接字时,我曾经通过从我的环回接口在该端口上发送一个数据包来解决这个问题,从而触发来自recvfrom 的返回。但是,这非常不雅,并且不能在 TCP 套接字上完成。

我知道另一种解决方法可能是使用 setsockopt 设置超时:这样我可以保证调用最终会返回,但这也很不优雅,而且效率也很低,因为我可能要等待几个在能够加入线程之前几秒钟。

所以我想知道是否有某种方法可以在套接字read 调用上触发EAGAIN,这与我会超时的方法不同,这样我就可以在我的主线程上调用一些@987654327 @on 我的套接字描述符和在另一个线程上对read 的调用会返回吗?

【问题讨论】:

如果正在侦听的套接字在另一个线程中关闭,recv 不会立即返回错误吗?使用O_NONBLOCK 是一个选项吗? 您的 TCP 线程是按照您在第一句话中所说的那样监听/接受,还是按照您在第二段中所说的那样阅读已建立的连接,还是两者兼而有之? 哎呀。对不起。我误用了我的话。我说的是从已经建立的连接中读取。 How to join a thread that is hanging on blocking IO? 的可能重复项 【参考方案1】:

我通常通过创建pipe() 并在阅读线程中使用select() 来解决这个问题。读取线程必须同时选择 TCP 套接字和管道的一端。每当您想关闭阅读器时,设置一个标志并将一些数据写入管道的另一端。

设置:

#include <unistd.h>

int signalPipe[2];

...

pipe(signalPipe);

读者:

while(running)

    FD_ZERO(&fds);
    FD_SET(tcpSocket, &fds);
    FD_SET(signalPipe[0], &fds);
    select(max(tcpSocket, signalPipe[0]) + 1, &fds, NULL, NULL, NULL);
    ...

其他话题:

// We want to stop now.
running = false;
write(signalPipe[1], "foo", 3);

【讨论】:

以上是关于在另一个线程上接收的套接字上触发 EAGAIN的主要内容,如果未能解决你的问题,请参考以下文章

Java 套接字:您可以从一个线程发送并在另一个线程上接收吗?

套接字关闭时取消阻止 recvfrom

Python Socket接收/发送多线程

从不同线程在同一个套接字上发送和接收不起作用

当没有数据要读取时,读取套接字会给出 errno EAGAIN,而且如果我断开网络连接

在 ICMP 套接字上接收数据