2

我正在使用C中的 POSIX 线程编写一个简单的多客户端服务器通信程序。每次连接新客户端时,我都会创建一个线程,即在.accept(...)main()

我已将accept(...)andpthread_create(...)放入一个while(1)循环中,以便服务器继续永远接受客户端。pthread_join(...)现在,线程退出后我应该在哪里编写例程。

更多信息:在线程的“启动例程”中,我使用了poll()& thenrecv()函数,再次在while(1)循环中不断轮询客户端的可用性并分别从客户端接收数据。线程在以下情况下退出:

1)要么poll()返回一些错误事件,要么客户端挂断。
2)recv()返回值 <= 0。

语言:C
平台:Suse Linux Enterprise Server 10.3 (x86_64)

4

3 回答 3

4

首先为每个客户端启动一个新线程可能很浪费,而且肯定不会扩展得很远。您应该尝试一个线程处理多个客户端(即调用poll多个套接字)的设计。事实上,这就是poll(2), epolletc 的设计目的。

话虽如此,在这种设计中,您可能根本不需要加入线程。您没有提到主线程需要来自已完成线程的信息的任何原因。换句话说,没有必要加入

只需将它们设置为“分离”(pthread_detachpthread_attr_setdetachstate),当它们的函数返回时它们将被自动清理。

于 2013-08-14T06:02:18.157 回答
1

问题是pthread_join阻塞调用线程直到线程退出。这意味着您不能真正调用它并希望线程已经退出,因为在线程退出之前主线程将无法执行任何其他操作。

一种解决方案是每个子线程都有一个由主线程轮询的标志,并且子线程在退出之前设置该标志。当主线程注意到标志被设置时,它可以加入子线程。

另一种可能的解决方案是,如果你有例如pthread_tryjoin_np(你应该有,因为你在 Linux 系统上)。然后其循环中的主线程可以简单地尝试以非阻塞方式加入所有子线程。

另一个解决方案可能是分离子线程。然后他们将自己运行,不需要加入。

于 2013-08-14T06:04:27.933 回答
1

啊,老干净的关机问题。

假设您可能希望在某些情况下完全断开服务器与所有客户端的连接,您的主线程将必须告诉客户端线程它们要断开连接。那么这怎么可能呢?

一种方法是在主线程和客户端线程之间有一个管道(每个客户端线程一个)。客户端线程在其对 poll() 的调用中包含该管道的文件描述符。这样主线程可以轻松地向客户端线程发送命令,告诉它终止。当 poll() 告诉它管道已准备好读取时,客户端线程读取命令。

因此,您的主线程可以通过管道向客户端线程发送某种命令,然后调用 pthread_join() 等待客户端线程自行整理并终止。

类似地,客户端线程可以使用另一个管道(每个客户端线程也有一个)将信息发送到主线程。主线程可以使用 poll() 来等待新的客户端连接和来自现有客户端线程的消息,而不是陷入对 accept() 的调用。poll() 的超时还允许主线程定期执行某些操作。

欢迎来到并发编程的 Actor 模型的世界。

当然,如果你不需要彻底关闭,那么你可以让线程在他们想要的时候终止,然后 ctrl c 程序来关闭它......

正如其他人所说,获得每个线程的工作平衡对于有效扩展很重要。

于 2013-08-14T06:58:54.547 回答