停止在recv()上阻塞的接收器线程
Stopping a receiver thread that blocks on recv()
我有一个聊天应用程序,它有一个单独的线程来监听传入的消息。
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
,要么在协议中包含显式退出消息。
#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 %dn", recv(cd, &buf, 1, 0));
pthread_join(thread, 0);
return 0;
}
您可以使用select()来等待传入的数据,并避免在recv()中阻塞。Select()也会阻塞,但您可以在设定的间隔后超时,以便while循环可以继续并检查来自主线程的退出信号:
while (main thread not calling for receiver to quit) {
if (tcpCon.hasData(500)) { // Relies on select() to determine that data is
// available; times out after 500 milliseconds
string message = tcpCon.tcpReceive(); // Relies on the recv() function
processIncomingMessage(message);
}
}
如果在另一个线程中关闭套接字,则recv()将退出。
从任何其他线程调用套接字上的close
将使recv
调用立即失败。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- 如何组织从提升日志接收器进行线程安全读取?
- 如何使用boost.thread运行多个接收器,每个线程应该分配给每个接收器?
- C++ 提升 UDP 接收器在放入线程时失败
- 为什么即使在使用 Qt::D irectConnection 之后,接收器的线程中仍会调用插槽?如何确保在另一个线程中调用它?
- 在C 中,发送者接收器模型中的多线程
- 停止在recv()上阻塞的接收器线程