繁体   English   中英

如何让在recv()上阻塞的线程正常退出?

[英]How to let a thread which blocks on recv() exit gracefully?

有一个这样的线程:

{  
    ......    
    while (1)
    {
        recv(socket, buffer, sizeof(buffer), 0);
        ......
    }
    close(socket);           
}  

由于线程在recv()调用时阻塞,如何让该线程正常退出?

您可以致电:-

shutdown(sock, SHUT_RDWR)    //on the remote end

检查这个出来。

不要在接收时阻止。 而是在“ select”上实现一个块,然后测试输入的fdset以确定是否有任何要读取的内容。

如果有要读取的数据,请调用recv。 如果不是,则循环,检查启动关闭时由另一个线程设置的“正在运行”挥发性布尔变量。

要么:

  1. 使用setsockopt()SO_RCVTIMEO设置读取超时,并在每次触发时检查一个状态变量,以查看是否已告诉自己停止读取。
  2. 如果要永远停止读取套接字,请使用shutdown(sd, SHUT_RD)其关闭以进行输入。 从现在开始,这将使recv()返回零。
  3. 将套接字设置为非阻塞模式,并使用带有超时的select()告诉您何时读取,并采用与上面(1)相同的状态变量策略。 但是非阻塞模式在发送操作中带来了相当大的复杂性,因此您应该首选上面的(1)或(2)。

您的伪代码缺少EOS和错误检查。 我希望它看起来并非如此。

声明全局退出标志:

int bExit = 0;

让关键部分对其进行测试:

 while(1)
 {
   ssize_t result = recv(socket, buffer, sizeof(buffer), 0);
   if ((-1 == result) && (EINTR == error) && bExit) 
   {
     break;
   }

   ...
 }

要破坏您的读者,请先设置退出标志

bExit = 1;

然后向阅读器线程发送信号

pthread_kill(pthreadReader, SIGUSR1);

注意:在本示例中,我遗漏的是对bExit防止并发访问。

这可以通过使用互斥量或适当的声明来实现。

声明一些“停止”布尔值,在每次recv()返回后检查它,如果设置了则终止。 要关闭,请设置布尔并从另一个线程关闭套接字。 阻塞的recv()将立即返回“错误”,但是“ cos您无论如何都将终止:

我可能会使用的信号,以@ ALK的优良答案 (还讨论了在这里 )。

或者,您可以使用多路复用的I / O。

在初始化时,创建一个全局管道(2)。 是时候结束程序了,关闭管道的写端-现在读端将立即选择(2)/ poll(2)可读(对于EOF)。 同时,让您的recv阻塞线程在例如无限阻塞的select(2)调用中将此管道的读取端及其套接字包括在内。 如果管道的读取端返回可读状态,则I / O线程知道是时候优雅地终止了。

该技术的主要警告是确保写端仅关闭一次,因为随后的朴素close(2)可能会压缩一些恰好被赋予与管道旧写端相同的描述符的无辜文件。

另外,将您的套接字设置为非阻塞:

int listen_sd = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (listen_sd < 0) {
    perror("socket() failed");
}

int on = 1;

//set socket to be non-blocking
int rc = ioctl(listen_sd, FIONBIO,(char *)&on);
if (rc < 0) {
    perror("ioctl() failed");
    close(listen_sd);
}

然后,您可以在套接字上调用recv(),它将不会阻塞。 如果没有要读取的内容,则将ERRNO全局变量设置为常量EWOULDBLOCK

int rc = recv(listen_sd, buffer, sizeof(buffer), 0);
if (rc < 0) {
    if (errno != EWOULDBLOCK) {
        perror("recv() failed");
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM