我正在使用C 中的POSIX线程编写简单的多客户端服务器通信程序。我每次连接一个新客户端时都会创建一个线程,即accept(...)
中的main()
例程之后。
我已将accept(...)
和pthread_create(...)
置于while(1)
循环内,以便服务器继续永久接受客户端。现在,在线程退出后我应该在哪里编写pthread_join(...)
例程。
更多信息:在线程的“开始例程”中,我使用了poll()
&然后recv()
函数再次在while(1)
循环内,以连续轮询客户端的可用性并分别从客户端接收数据。该线程在以下情况下退出:
1)poll()
返回某个错误事件或客户端挂起
2)recv()
返回值< = 0。
语言:C
平台:Suse Linux Enterprise Server 10.3(x86_64)
答案 0 :(得分:4)
首先为每个客户开始一个新线程可能是浪费,肯定不会扩展到很远。您应该尝试一种线程处理多个客户端的设计(即在多个套接字上调用poll
)。实际上,这就是为poll(2)
,epoll
等设计的。
话虽如此,在这个设计中你可能根本不需要加入线程。你没有提到为什么主线程需要来自完成的线程的信息的任何原因。换句话说,没有必要加入。
只需将它们设置为“已分离”(pthread_detach
或pthread_attr_setdetachstate
),它们会在函数返回时自动清除。
答案 1 :(得分:1)
问题是pthread_join
阻塞调用线程,直到线程退出。这意味着你无法真正调用它并希望线程已经退出,因为主线程在线程退出之前将无法执行任何其他操作。
一种解决方案是每个子线程都有一个由主线程轮询的标志,子线程在退出之前设置该标志。当主线程注意到正在设置的标志时,它可以加入子线程。
另一种可能的解决方案是,如果你有例如pthread_tryjoin_np
(因为你在Linux系统上,你应该拥有它)。然后,它的循环中的主线程可以简单地尝试以非阻塞方式连接所有子线程。
另一种解决方案可能是分离子线程。然后他们将自己运行,不需要加入。
答案 2 :(得分:1)
啊,'干净的关机问题。
假设您可能希望在某些情况下干净地断开服务器与所有客户端的连接,您的主线程必须告诉客户端线程他们要断开连接。那怎么可能呢?
一种方法是在主线程和客户端线程之间建立一个管道(每个客户端线程一个)。客户端线程在调用poll()时包含该管道的文件描述符。这样主线程就可以轻松地向客户端线程发送命令,告诉它终止。当poll()告诉管道已经准备好读取时,客户端线程会读取命令。
因此,您的主线程可以通过管道向客户端线程发送某种命令,然后调用pthread_join()等待客户端线程整理并终止。
类似地,客户端线程可以使用另一个管道(每个客户端线程一个管道)将信息发送到主线程。主线程可以使用poll()来等待新的客户端连接和来自现有客户端线程的消息,而不是停留在对accept()的调用中。 poll()上的超时也允许主线程定期执行某些操作。
欢迎来到并发编程的演员模型世界。
当然,如果你不需要一个干净的关闭,那么你可以让线程在他们想要的时候终止,然后只需按住程序关闭它......
正如其他人所说,每个线程的平衡工作对于有效扩展非常重要。