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

时间:2015-02-20 08:09:14

标签: c++ windows multithreading sockets network-programming

我想处理300到400个客户端连接,但我不想为每个客户端连接创建一个线程(或者创建400个线程有什么问题吗?)。

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


修改: read()更改为recv()

3 个答案:

答案 0 :(得分:2)

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

使用线程池,您有一个线程接收请求,然后将这些请求提供给您的线程池工作。 所以你不会有一个在等待读取时阻塞的线程。当有东西需要阅读时,你就可以使用线程池了。

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

答案 1 :(得分:2)

正如user743414已经指出的那样,对许多线程来说并不是一个好主意。但主要的问题在于你的阻止read恕我直言。如果有东西要读,你应该使用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);

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

答案 2 :(得分:1)

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

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