c++ - 停止阻塞在 recv() 上的接收器线程

标签 c++ c sockets networking

我有一个聊天应用程序,它有一个单独的线程来监听传入的消息。

while (main thread not calling for receiver to quit) {
  string message = tcpCon.tcpReceive();    // Relies on the recv() function
  processIncomingMessage(message);
}

这种工作方式有一个大问题。大多数时候,循环将阻塞在 recv() 上,因此接收线程不会退出。在几秒钟后不强制线程终止的情况下,解决此问题的正确方法是什么?

最佳答案

使用 shutdown() 关闭套接字,为所有接收器关闭它。

这会在我的系统上打印出“recv returned 0”,表明接收器正常关闭。注释掉 shutdown() 并观察它永远挂起。

从长远来看,OP 应该修复设计,使用 select 或在协议(protocol)中包含明确的退出消息。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>

/* Free on my system. YMMV */
int port = 7777;
int cd;

void *f(void *arg)
{
    /* Hack: proper code would synchronize here */
    sleep(1);

    /* This works: */
    shutdown(cd, SHUT_RDWR);

    close(cd);
    return 0;
}

int main(void)
{
    /* Create a fake server which sends nothing */
    int sd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in sa = { 0 };
    const int on = 1;
    char buf;
    pthread_t thread;
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    sa.sin_port = htons(port);
    setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);

    /* Other error reporting omitted for clarity */
    if (bind(sd, (const struct sockaddr*)&sa, sizeof sa) < 0) {
        perror("bind");
        return EXIT_FAILURE;
    }

    /* Create a client */
    listen(sd, 1);
    cd = socket(AF_INET, SOCK_STREAM, 0);
    connect(cd, (const struct sockaddr*)&sa, sizeof sa);
    accept(sd, 0, 0);

    /* Try to close socket on another thread */
    pthread_create(&thread, 0, f, 0);
    printf("recv returned %d\n", recv(cd, &buf, 1, 0));
    pthread_join(thread, 0);

    return 0;
}

关于c++ - 停止阻塞在 recv() 上的接收器线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8049677/

相关文章:

java - 通过 TCP 套接字发送数据包

"[Errno -2] Name or service not known"上的 Python 套接字 block ?

c++ - 链接 qt5 库通过 cmake 自动将额外的 fPIcflags传递给 nvcc 编译器,导致错误

C++ 在模板编译器错误中使用模板

c - 在 C 中的宏预处理中生成标签

c - 无效指针条件引发段错误

c++ - 不得删除 C++ 或 C 运算符之间的空格的示例

c++ - vector 迭代器不可取消引用。成对的优先队列。

c++ - 动态创建的字符串分配在堆或堆栈上 - C

node.js - 通过 file.createWriteStream() 流式传输到 GCP 时,获取 ESOCKETTIMEOUT、ECONNRESET 或套接字挂起大文件