在进行套接字编程时,使用多线程,
如果线程在接受函数上被阻塞,
并且主线程正在尝试关闭该进程,
如何打破接受功能以安全地 pthread_join?
我对如何通过将自身连接到自己的端口以破坏接受功能来做到这一点的记忆模糊。
任何解决方案将不胜感激。
干杯
一些选择:
a) 使用非阻塞
b) 使用 AcceptEx() 等待额外的信号,(Windows)
c) 关闭来自另一个线程的侦听套接字以使 Accept() 返回错误/异常。
d) 从另一个线程打开一个临时本地连接以使 Accept() 与临时连接一起返回
根据您的系统,如果可用,我将使用一个select
函数来等待服务器套接字进行读取,表明套接字正在尝试连接。可以将等待连接的时间量设置/调整为每次您想要等待客户端连接的时间(无穷大,到秒,到 0,这将只是检查并返回)。需要检查返回状态以查看是否已达到时间限制(没有套接字正在尝试连接),或者是否有东西等待服务(您的服务器套接字表明有一个客户端想要连接)。accept
然后,您可以根据返回的状态 执行知道有一个要连接的套接字。
典型的方法是不使用accept()
,除非有什么可以接受的!做到这一点的方法是poll()
在一个循环中使用适当的超时时间到相应的套接字。循环检查是否因为设置了适当的同步标志而退出。
另一种方法是向阻塞线程发送信号,例如,使用pthread_kill()
. accept()
这会通过适当的错误指示摆脱阻塞。同样,下一步是检查一些标志以查看线程是否要退出。不过,我的偏好是第一种方法。
如果可用,我会在循环中使用带有超时的选择函数来实现此功能。
正如格伦建议的那样
具有超时值的 select 函数将等待套接字连接一段时间。如果套接字尝试连接,则可以在此期间接受它。通过使用超时循环此选择,可以检查新连接,直到满足中断条件。
这是一个例子:
std::atomic<bool> stopThread;
void theThread ( std::atomic<bool> & quit )
{
struct timeval tv;
int activity;
...
while(!quit)
{
// reset the time value for select timeout
tv.tv_sec = 0;
tv.tv_usec = 1000000;
...
//wait for an activity on one of the sockets
activity = select( max_sd + 1 , &readfds , NULL , NULL , &tv);
if ((activity < 0) && (errno!=EINTR))
{
printf("select error");
}
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
...
}
}
int main(int argc, char** argv)
{
...
stopThread = false;
std::thread foo(theThread, std::ref(stopThread));
...
stopThread = true;
foo.join();
return 0;
}
一个更完整的“选择”示例http://www.binarytides.com
我对 C++ 很陌生,所以我确信我的代码和答案可以改进。
听起来您正在寻找的是这样的:您设置了一个特殊的标志变量,该变量对于侦听/接受套接字是已知的,然后让主线程打开与侦听/接受套接字的连接。监听/接受套接字/线程每次接受连接时都必须检查标志,以便知道何时关闭。
通常,如果您想进行多线程网络,您将在建立连接(或准备建立连接)后生成一个线程。如果你想降低开销,线程池并不难实现。