2010-08-12 68 views
2

风云作弊:命名管道:许多客户。如何慎重创建线程?线程池?

我在Windows上使用命名管道,使用C++。

服务器通过CreateNamedPipe创建一个命名管道实例,并等待客户端通过ConnectNamedPipe进行连接。

客户端每次调用CreateFile来访问命名管道时,服务器都会使用CreateThread创建一个线程来为该客户端提供服务。在这之后,服务器再次循环,通过创建一个CreateNamedPipe时管道实例并通过ConnectNamedPipe监听下一个客户端,等...

问题:

每个客户端请求触发服务器上的CreateThread。如果客户快速而激烈地出现,会有很多对CreateThread的调用。

问题:

Q1:是否有可能重新使用已经创建的线程来服务未来的客户端请求? 如果这是可能的,我应该怎么做?

Q2:线程池会在这种情况下提供帮助吗?

回答

1

在Windows上,构建并发服务器的最有效方法是使用带有完成端口的异步模型。但是,您可以使用线程池并使用阻塞I/O,因为这是一个更简单的编程抽象。

Vista/Windows 2008提供了线程池抽象。

+0

感谢您的建议 - I/O完成端口看起来很有前途。我会读更多关于它。 (我的目标是XP及以上)。 – moog 2010-08-12 08:06:22

3

我今天写了一个命名管道服务器,使用IOCompletion端口来查看。

的基本逻辑流程是:

  • 我通过CreateNamedPipe时创建的第一个命名管道
  • 我创建使用手柄主体IO完成端口对象:CreateIoCompletionPort
  • 我创建工作线程池 - 作为一个拇指吸,CPU x2。每个工作线程在一个循环中调用GetQueuedCompletionStatus。
  • 然后调用ConnectNamedPipe以重叠结构传递。当此管道连接时,GetQueuedCompletionStatus调用之一将返回。
  • 我的主线程通过调用GetQueuedCompletionStatus来加入工作池。

这是真的。

每次线程从GetQueuedCompletionStatus返回时,都会因为关联的管道已连接,已读取数据或已关闭。每次连接一个管道时,我立即创建一个未连接的管道来接受下一个客户端(可能一次有多个等待中的客户端),并在当前管道上调用ReadFile,传递重叠结构 - 确保数据到达GetQueuedCompletionStatus会告诉我这件事。

在函数返回失败代码的情况下会遇到一些恼人的情况,但GetLastError()是成功的。由于功能“失败”,您必须立即处理成功,因为没有发布排队完成状态。相反,(如果数据立即可用,我相信Vista会添加一个API来“解决”这个问题),重叠的函数可以返回成功,但排队的完成状态也会发布,因此在这种情况下请注意不要双重处理数据。