线程池如何让我处理许多客户端连接?

我想处理300到400个客户端连接,但是我不想为每个客户端连接创build一个线程(或者在创build400个线程时是否有任何错误?)。

所以我读过,我应该使用线程池来解决这个问题,但我无法理解一个线程池如何实际上解决这个问题。 我的意思是,在我对线程池的理解中,有数量有限的线程开始执行任务。 但是一旦一个线程接受一个recv()任务,它将立即阻塞,如果没有什么可读的! 所以不是解决scheme应该是我应该有一个机制,让我知道是否有什么事情要读之前,实际上试图读取它? 那么线程池究竟如何解决了我处理多个客户端连接的问题呢?


编辑:read()更改为recv()

正如user743414已经指出的,对于很多线程来说都不是一个好主意。 但主要的问题在于恕我直言在你的阻止read 。 如果有东西要阅读,你只能使用阅读。 使用select来找出哪个套接字有东西要读取,并将其分配给线程池中的工作线程是通常的方法。 使用Windows,您应该使用WSASockets。

您在单个线程中使用select 。 比你使用select的结果(它会告诉你哪个套接字需要动作)来分派连接到工作线程。

你写了你使用微软。 拿样品:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms742219(v=vs.85).aspx

搜索代码

  //----------------------------------------- // If data has been received, echo the received data // from DataBuf back to the client iResult = WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL); if (iResult != 0) { wprintf(L"WSASend failed with error = %d\n", WSAGetLastError()); } 

你可以用你的线程池代替(伪代码):

 mythreadpool *thread=takeOrCreateThreadFromThreadPool(); thread->callWith(&DataBuf,&RecvBytes); 

你会发现许多不同但很好的线程池实现将使用类似的方法。

创建300 – 400个线程应该可以工作,但不是最好的解决方案。 上下文切换是您必须搜索的关键字。 上下文切换是昂贵的。 更多线程的另一个问题是每个线程获得1 MB的堆栈内存,并且内存是有限的。 你可以很容易地尝试这个检查你可以创建多少个线程。

有了一个线程池,你有一个线程接收到一个请求,然后把这些请求给你的线程池来工作。 所以你不会有等待读取时阻塞的线程。 当有东西需要阅读时,你的线程池正在工作。

另一个更好的选择是在Windows I / O完成端口上。 类似的技术也可以在Linux上使用。

线程池有帮助,因为你可能不会有所有的400个连接不断地发送和接收数据,所以你的应用程序只需要少量的线程来管理它们。

一个线程可以监控所有连接(使用select作为例子),一旦选择解锁,它就会遍历所有需要注意的套接字并将它们传递给线程池。 如果select指定套接字已经接收到数据,那么read将不会被阻塞(并且仍然可以将读取的超时设置为0)