Run*_*ner 9 windows delphi winapi asynchronous named-pipes
问题:
设计一个高效且非常快速的命名管道客户端服务器框架.
现状:
我已经有经过验证的生产测试框架.它很快,但是每个管道连接使用一个线程,如果有很多客户端,线程数可能会很快变高.我已经使用了可以根据需要扩展的智能线程池(事实上的任务池).
我已经使用OVERLAPED模式管道,但后来我使用WaitForSingleObject或WaitForMultipleObjects阻塞,这就是为什么我需要在服务器端每个连接一个线程
期望的解决方案:
客户端很好,但在服务器端,我想只为每个客户端请求使用一个线程,而不是每个连接.因此,不是在客户端的整个生命周期中使用一个线程(连接/断开连接),而是每个任务使用一个线程.所以只有当客户端请求数据而不再需要时.
我在MSDN上看到了一个使用OVERLAPED结构数组的示例,然后使用WaitForMultipleObjects等待它们全部.我发现这是一个糟糕的设计.我在这里看到两个问题.首先,你必须维护一个可以变得非常大的数组,删除将是昂贵的.其次,你有很多事件,每个阵列成员一个.
我也看到了完成端口,比如CreateIoCompletionPort和GetQueuedCompletionStatus,但是我看不出它们是如何更好的.
我想要的是ReadFileEx和WriteFileEx所做的事情,它们在操作完成时调用回调例程.这是一种真正的异步编程风格.但问题是ConnectNamedPipe不支持它,而且我看到线程需要处于警报状态,你需要调用一些*Ex函数来实现它.
那么这样的问题如何最好地解决了?
以下是MSDN的工作方式:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v = vs.85).aspx
我用这种方法看到的问题是,如果WaitForMultipleObjects的限制是64个句柄,我怎么看不到你可以同时连接100个客户端.当然,我可以在每次请求后断开管道,但想法是在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;
Run Code Online (Sandbox Code Playgroud)
这样我们只有一个接受connect/disconnect/onData事件的监听器线程.线程池(工作线程)仅处理实际请求.这样,5个工作线程可以为许多连接的客户端提供服务.
PS我当前的代码不应该很重要.我在Delphi中编写它,但它的纯WinAPI,所以语言无关紧要.
编辑:
现在IOCP看起来像解决方案:
I/O完成端口提供了一种有效的线程模型,用于处理多处理器系统上的多个异步I/O请求.当进程创建I/O完成端口时,系统会为请求创建关联的队列对象,这些请求的唯一目的是为这些请求提供服务.处理许多并发异步I/O请求的进程可以通过将I/O完成端口与预分配的线程池结合使用,而不是在接收I/O请求时创建线程,从而更快速有效地执行此操作.
如果服务器必须处理超过 64 个事件(读/写),则任何使用 WaitForMultipleObjects 的解决方案都变得不可行。这就是 Microsoft 将 IO 完成端口引入 Windows 的原因。它可以使用最合适的线程数(通常是处理器/核心的数量)来处理大量的 IO 操作。
IOCP的问题是很难正确实施。隐藏的问题就像地雷一样在现场传播:[ 1 ]、[ 2 ](第 3.6 节)。我建议使用一些框架。在谷歌上搜索了一下,为 Delphi 开发人员推荐了名为Indy的东西。也许还有其他人。
此时,如果命名管道意味着编写我自己的 IOCP 实现,我将忽略命名管道的要求。这不值得悲伤。
| 归档时间: |
|
| 查看次数: |
4287 次 |
| 最近记录: |