1

我正在尝试实现一个 TCP 服务器,它是一个更大项目的一部分。基本上,服务器应该能够与任意数量的客户端(至少 32 个)保持 TCP 连接,并为任何请求服务的客户端提供服务。在我们的场景中,假设一旦客户端连接到服务器,它将永远不会关闭连接,除非发生某种故障(例如运行客户端的机器发生故障),并且它会重复请求服务服务器。所有其他客户端也是如此,即每个客户端都将保持与服务器的连接并执行事务。

现在我使用select()berkely 套接字 API 的系统调用,当我们有少量客户端(比如 10 个)时它工作正常。但是服务器需要扩展到尽可能高的水平,因为我们在 16 核机器上实现它。为此,我查看了各种多线程设计技术,例如每个客户端一个线程等,我认为最好的一种是线程池设计。现在当我即将实现时,我遇到了一些问题:如果我指定主线程接受任意数量的传入连接并将每个连接文件描述符保存在数据结构中,并且我有一个线程池,我将如何获得用于轮询特定客户端是否正在请求服务的线程。对于客户端联系服务器并在获得服务后关闭连接的场景,该设计非常简单,这样我们就可以从池中选择一个线程,为客户端提供服务,然后将其推回池中以供将来处理连接。但是,当我们必须为一组保持连接并间歇性地请求服务的客户端提供服务时,最好的方法是什么。所有帮助将不胜感激,因为我真的陷入了困境。谢谢。

4

2 回答 2

2

Use pthreads, with one thread per CPU plus one extra thread.

The extra thread (the main thread) listens for new connections with the listen() system call, accepts the new connections with accept(), then determines which worker thread currently has the least number of connections, acquires a lock/mutex for that worker thread's "pending connections" FIFO queue, places the descriptor for the accepted connection onto the worker thread's "pending connections" FIFO queue, and sends a "check your queue" notification (e.g. using a pipe) to the worker thread.

The worker threads use "select()", and send/receive data to whatever connections they've accepted. If/when a worker thread receives a "check your queue" notification from the main thread it would acquire the lock/mutex for its "pending connections" FIFO queue and add any newly accepted connections to its "fd_set" list.

For 1024 connections and 16 CPUs; you might end up with one main thread waiting for new connections (but doing almost nothing as you wouldn't be expecting many new connections), and 16 worker threads handling an average of 64 connections each.

于 2012-01-29T23:55:18.030 回答
0

每个客户端一个线程几乎可以肯定是最好的设计。确保在等待新连接时始终至少有一个线程被阻塞accept- 这意味着在接受成功后,如果它是最后一个线程,您可能需要在继续之前创建一个新线程。我发现信号量是跟踪生成新侦听线程需求的一个很好的原语。

于 2012-01-30T00:40:38.853 回答