【问题标题】:Blocking pipe ConnectNamedPipe does not trigger阻塞管道 ConnectNamedPipe 不会触发
【发布时间】:2020-05-29 03:49:08
【问题描述】:

我想使用命名管道进行 IPC。 这是我试图在两个进程之间进行通信的测试客户端/服务器 客户端代码:

#include <iostream>
#include <Windows.h>

int main()
{
    HANDLE pipe = CreateFileA("\\\\.\\pipe\\DokiDoki", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (pipe != INVALID_HANDLE_VALUE) {
        char buffer[] = "DokiDoki from the other side :P";
        DWORD bytesWritten;
        WriteFile(pipe, static_cast<LPCVOID>(buffer), sizeof(buffer), &bytesWritten, NULL);
        std::cout << "Done!\n";
        CloseHandle(pipe);
    }
    else {
        std::cout << "Could not get a handle to the pipe!\n";
        return 1;
    }
    return 0;
}

服务器代码:

#include <iostream>
#include <array>
#include <Windows.h>

int main()
{
    char buffer[1024];
    HANDLE pipe = CreateNamedPipeA("\\\\.\\pipe\\DokiDoki", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, sizeof(buffer), sizeof(buffer), NMPWAIT_USE_DEFAULT_WAIT, NULL);
    while (pipe != INVALID_HANDLE_VALUE) {
        if (!ConnectNamedPipe(pipe, NULL)) {
         //Setting a breakpoint here will never trigger.
            DWORD bytesRead = 0;    
            while (ReadFile(pipe, static_cast<LPVOID>(buffer), sizeof(buffer) - 1, &bytesRead, NULL)) {
                std::cout << buffer << std::endl;
            }
        }
        DisconnectNamedPipe(pipe);
    }
    return 0;
}

程序在 ConnectNamedPipe 处停止并且不会执行任何其他指令,即使客户端连接并写入管道也是如此。 WriteFile(在客户端)返回 true。

【问题讨论】:

  • 查看MSDN example
  • @RemyLebeau 提醒我这个 API 有多么糟糕。 ConnectNamedPipe() 应该返回一个新句柄,并且您不必重新创建管道或处理 fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 废话。

标签: c++ windows winapi pipe


【解决方案1】:

ConnectNamedPipe 如果成功则返回一个非零值,这就是它不起作用的原因。 将if (!ConnectNamedPipe(pipe, NULL)) 更改为if (ConnectNamedPipe(pipe, NULL)) 似乎工作正常。

【讨论】:

  • 虽然你说的是真的,但那不是你最初声称的。您使代码看起来在ConnectNamedPipe() 上被阻塞,在这种情况下,返回值无论哪种方式都无关紧要。除非您歪曲了问题并且实际上将断点放在了 ConnectNamedPipe() 之后并且由于没有输入 if 块而没有到达它。
  • 所以它根本没有停在ConnectNamedPipe()。它通过断开连接,顺便说一句,不应该在失败时执行。
  • 这也不是正确的答案。您还必须处理 ERROR_PIPE_CONNECTED,因为某些原因只有 Microsoft 才知道,这种情况是错误,而不是成功。有关详细信息,请参阅 MSDN 示例。
  • @user207421 - ERROR_PIPE_CONNECTED (STATUS_PIPE_CONNECTED) 的原因是已知的 - 这意味着客户端在服务器调用 ConnectNamedPipe 之前连接到管道。还存在另一种特殊情况-STATUS_PIPE_CLOSING(转换为ERROR_NO_DATA win32 代码)-表示客户端已经连接和断开连接(即关闭自身管道句柄)。有趣的是,真正的客户端也可以将一些数据写入管道 - 它可以被服务器读取(尽管错误名为 ERROR_NO_DATA
  • @RbMm 那是它在文档中所说的,但它什么也没解释。这里的问题是他们为什么将成功案例指定为错误?客户端在通话之前或之后连接有什么区别?服务器代码可以以任何一种方式进行。 TCP accept() 没有做出这种区分,而且没有人会错过它。
猜你喜欢
  • 1970-01-01
  • 2023-03-17
  • 2011-12-05
  • 1970-01-01
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多