未发出信号的非阻塞 ConnectNamedPipe 事件

Posted

技术标签:

【中文标题】未发出信号的非阻塞 ConnectNamedPipe 事件【英文标题】:Non-blocking ConnectNamedPipe event not getting signaled 【发布时间】:2013-01-13 18:08:04 【问题描述】:

我从命名管道开始,需要将它们用于两个本地进程之间的 IPC。我在非阻塞重叠模式下使用管道的服务器和客户端进程。

一切正常(服务器成功接收到客户端发送的字符串),除了通过 OVERLAPPED 结构传递给 ConnectNamedPipe() 的事件未按预期发出信号(客户端连接时发出信号)。

当服务器在 WaitForSingleObject() 调用上被阻塞时,连接到管道的客户端进程发送了它的数据并终止了,但事件没有得到信号。我错过了什么?

服务器代码:

HANDLE hPipe = ::CreateNamedPipeW(
    L"\\\\.\\pipe\\ThePipe",
    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
    1,
    4096,
    4096,
    100,
    nullptr);

OVERLAPPED ov = 0;
ov.hEvent = ::CreateEventW(nullptr, TRUE, FALSE, nullptr);

BOOL retVal = ::ConnectNamedPipe(hPipe, &ov);

if (retVal == 0)

    DWORD err = ::GetLastError();
    if (err == ERROR_IO_PENDING)
    
        ::WaitForSingleObject(ov.hEvent, 30000);
    
    if (err == ERROR_PIPE_LISTENING)
    
        ::WaitForSingleObject(ov.hEvent, 30000);    // this blocks until time-out???
    

【问题讨论】:

它是否收到 ERROR_IO_PENDING? (你最好让这种情况容易区分,或者你必须附加到进程,看看它在哪里等待) 【参考方案1】:

您不应将(不推荐使用)PIPE_NOWAIT 与重叠模式一起使用。 PIPE_NOWAIT 使 ConnectNamedPipe 立即返回 ERROR_PIPE_LISTENING 如果没有客户端连接;不会发生重叠 I/O,等待事件也没用。

要么设置PIPE_NOWAIT 并定期轮询管道直到成功,要么设置FILE_FLAG_OVERLAPPED 并使用事件来检查/等待完成。

【讨论】:

解决了我的问题。非常感谢!微软真的应该更新这方面的文档。 来自 CreateNamedPipe 上的 MSDN 页面:“请注意,为了与 Microsoft LAN Manager 2.0 版兼容,支持非阻塞模式,不应使用命名管道实现异步 I/O。” 有关于不在异步模式下使用 ConnectNamedPipe 的警告。相反,可以将 OVERLAPPED 结构传递给 ReadFile 以等待读取。

以上是关于未发出信号的非阻塞 ConnectNamedPipe 事件的主要内容,如果未能解决你的问题,请参考以下文章

如何从 non_GUI 类和我们可以在主 GUI 类中检测到的非 GUI 线程发出信号

基于select的非阻塞ftp传输(未优化)

基于select的非阻塞ftp传输(未优化)

QTcpSocket Disconnected() 未发出信号

Gio.SimpleAction 未发出更改状态信号

Lua 对空 FIFO 的非阻塞读访问