停止在recv()上阻塞的接收器线程 [英] Stopping a receiver thread that blocks on recv()

查看:151
本文介绍了停止在recv()上阻塞的接收器线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个聊天应用程序,该应用程序具有一个单独的线程来侦听传入的消息.

I have a chat application that has a separate thread to listen for incoming messages.

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

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

This way of working has one big problem. Most of the time, the loop will be blocking on recv() so the receiver thread won't quit. What would be a proper way to tackle this issue without forcing thread termination after a couple of seconds?

推荐答案

使用shutdown()关闭套接字以关闭所有接收器.

Close the socket with shutdown() to close it for all receivers.

这将在我的系统上打印出"recv返回0",表明接收器有序关闭.注释掉shutdown()并观看它永远挂起.

This prints out 'recv returned 0' on my system, indicating that the receiver saw an orderly shutdown. Comment out shutdown() and watch it hang forever.

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

Longer term, OP should fix the design, either using select or including an explicit quit message in the 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;
}

这篇关于停止在recv()上阻塞的接收器线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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