windows - 命名管道高效异步设计

标签 windows delphi winapi asynchronous named-pipes

问题:

设计一个高效且非常快速的命名管道客户端服务器框架。

当前状态:

我已经拥有经过实战验证的生产测试框架。它速度很快,但是它为每个管道连接使用一个线程,如果有很多客户端,线程数可能很快就会很高。我已经使用了可以根据需要扩展的智能线程池(实际上是任务池)。

我已经为管道使用了 OVERLAPED 模式,但随后我使用 WaitForSingleObject 或 WaitForMultipleObjects 进行阻塞,这就是为什么我需要在服务器端为每个连接创建一个线程

所需的解决方案:

客户端就这样很好,但在服务器端,我想为每个客户端请求而不是每个连接使用一个线程。因此,我不会在客户端的整个生命周期(连接/断开连接)中使用一个线程,而是为每个任务使用一个线程。因此仅当客户端请求数据时才可以。

我在 MSDN 上看到一个示例,它使用 OVERLAPED 结构数组,然后使用 WaitForMultipleObjects 等待它们。我觉得这是一个糟糕的设计。我在这里看到两个问题。首先,您必须维护一个可以增长到相当大的数组,并且删除操作的成本很高。其次,您有很多事件,每个数组成员一个。

我还看到了完成端口,比如 CreateIoCompletionPortGetQueuedCompletionStatus ,但我看不出它们有什么更好的地方。

我想要的东西是ReadFileExWriteFileEx做,他们调用回调例程 当操作完成时。这是一种真正的异步编程风格。但问题是 ConnectNamedPipe 不支持那个,而且我看到线程需要处于可警报状态,你需要调用一些 *Ex 函数来实现它。

那么如何最好地解决这样的问题呢?

这是 MSDN 的做法:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v=vs.85).aspx

我在这种方法中看到的问题是,如果限制为 WaitForMultipleObjects,我看不出如何同时连接 100 个客户端。是 64 个句柄。当然,我可以在每次请求后断开管道,但我的想法是像在 TCP 服务器中一样建立一个永久的客户端连接,并在整个生命周期中跟踪客户端,每个客户端都有唯一的 ID 和客户端特定数据。

理想的伪代码应该是这样的:

repeat
  // wait for the connection or for one client to send data
  Result = ConnectNamedPipe or ReadFile or Disconnect; 

  case Result of
    CONNECTED: CreateNewClient; // we create a new client
    DATA: AssignWorkerThread; // here we process client request in a thread
    DISCONNECT: CleanupAndDeleteClient // release the client object and data
  end;
until Aborted;

这样一来,我们只有一个接受连接/断开连接/onData 事件的监听器线程。线程池(工作线程)只处理实际的请求。这样 5 个工作线程可以为许多连接的客户端提供服务。

附言 我当前的代码应该不重要。我在 Delphi 中对此进行了编码,但它是纯 WinAPI,因此语言无关紧要。

编辑:

目前 IOCP 看起来像是解决方案:

I/O completion ports provide an efficient threading model for processing multiple asynchronous I/O requests on a multiprocessor system. When a process creates an I/O completion port, the system creates an associated queue object for requests whose sole purpose is to service these requests. Processes that handle many concurrent asynchronous I/O requests can do so more quickly and efficiently by using I/O completion ports in conjunction with a pre-allocated thread pool than by creating threads at the time they receive an I/O request.

最佳答案

如果服务器必须处理超过 64 个事件(读/写),那么任何使用 WaitForMultipleObjects 的解决方案都变得不可行。这就是微软向 Windows 引入 IO 完成端口的原因。它可以使用最合适的线程数(通常是处理器/内核的数量)处理大量的 IO 操作。

IOCP的问题是很难正确实现。隐藏的问题像地雷一样在该领域传播:[ 1 ], [ 2 ](第 3.6 节)。我建议使用一些框架。小谷歌搜索建议称为 Indy 的东西对于 Delphi 开发人员。可能还有其他的。

在这一点上,如果这意味着编写我自己的 IOCP 实现,我将忽略对命名管道的要求。这不值得悲伤。

关于windows - 命名管道高效异步设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17805770/

相关文章:

C++ URLencode 库(支持 Unicode)?

mysql - 该系统最有效的架构是什么? (推或拉)

c++ - 生成 RSA-2048 key (公钥和私钥)

c++ - WinAPI 窗口不出现

c++ - 如何正确设置 CMakeLists.txt 文件?

Java nio 监视服务 : Watch Windows drives list

c++ - 结构中字段对齐的奇怪行为

delphi - 向客户发布部分源代码

HTML 5 真的可以做 Win 32call 吗?

c++ - 如何使用设备 ID 获取 USB 硬件 ID?