无法打开 Windows 命名管道进行写入?

Posted

技术标签:

【中文标题】无法打开 Windows 命名管道进行写入?【英文标题】:Can't open Windows Named Pipe for writing? 【发布时间】:2018-10-29 19:05:01 【问题描述】:

我不明白为什么我什至无法打开命名管道来写入我在另一个进程中创建的内容。

我得到了错误

231(所有管道实例都忙)。

作者(客户):

#include "Windows.h"
#include <stdio.h>
#include <errno.h>

int main()

    HANDLE hpipe;
    DWORD written;
    char msg[] = "play asdf.wav";

    hpipe = CreateFileA("\\\\.\\pipe\\isp-control",
               GENERIC_WRITE | GENERIC_READ,
               0, NULL, OPEN_EXISTING, 0, NULL);

    if (hpipe != INVALID_HANDLE_VALUE)
    
      WriteFile(hpipe, msg, strlen(msg) + 1, &written, NULL);
      printf("wrote %d bytes of %d: '%s'\n", written, strlen(msg) + 1, msg);

      CloseHandle(hpipe);
    
    else
    
      printf("error %d opening pipe (handle %d)\n", GetLastError(), (int) hpipe);
      return 1;
    

    return 0;

阅读器(服务器)之前已经创建了这样的管道(注意 4 个实例,所以一个应该是免费的,不是吗?)

hpipe_ = CreateNamedPipeA("\\\\.\\pipe\\isp-control",
             PIPE_ACCESS_DUPLEX,
             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
             4, // number of instances
             1024 * 16, // output buffer size
             65535,  // input size
             2000, // default timeout ms 
             NULL);

然后使用PeekNamedPipe查看是否有数据要使用ReadFile读取或发送超时。

【问题讨论】:

但是你在服务器中调用ConnectNamedPipe 吗? 没有minimal reproducible example 的服务器代码很难诊断问题 注意 4 个实例,所以一个应该是免费的,不是吗? - 但无论如何您都需要致电 CreateNamedPipe 4 次创建 4 个实例(1 个调用仅创建单个实例)。连接断开后 - 您需要调用 DisconnectNamedPipe + ConnectNamedPipe 再次收听具体实例 感谢您对实例的澄清。服务器端缺少ConnectNamedPipe。现在我遇到了其他错误,但为了不完全改变问题,我用完整的源代码开始了一个新的:***.com/questions/53069904/… 【参考方案1】:

CreateNamedPipe 的第 4 个参数 - nMaxInstances - 这是可以为此管道创建的最大实例数。

所以这不是在单个调用中创建的实例计数,而是可以创建的最大计数。对CreateNamedPipe 的一次调用始终会创建一 (1) 个管道实例。如果您想要 4 个实例 - 您需要拨打 CreateNamedPipe 4 次。最初也是在侦听状态下创建的管道,因此客户端可以通过调用CreateFile 连接到它。但是在连接断开后(因为客户端关闭了自己的句柄)并且您想要接受同一个管道实例的新客户端连接 - 您需要调用 DisconnectNamedPipe 然后 ConnectNamedPipe - 只有在这个新客户端可以再次连接到同一个管道实例之后.

但无论如何,即使您只创建单个管道实例,通过单个调用 CreateNamedPipeA - 第一个客户端也可以连接到它。错误 231 - 我猜真正的错误来源是 STATUS_PIPE_NOT_AVAILABLE(命名管道的实例不能 发现处于侦听状态) - 您可以在 CreateFile 失败后通过调用 RtlGetLastNtStatus() 进行检查,而不是 GetLastError() 说管道名称有效,访问没有问题,但有人已经连接(可能已经断开连接) 到管道 - 永远不要先调用 CreateFile 返回此错误

【讨论】:

感谢清理 API,我并不清楚连接顺序。你是对的,它是 0xC00000AC (STATUS_PIPE_NOT_AVAILABLE)。但即使我在读取循环中执行ConnectNamedPipe 然后DisconnectNamedPipe,大多数时候我都会得到相同的状态“所有实例都被占用”。我将编辑问题以获得完整的示例来显示我在做什么(错误)。 我用包含上述提示的完整源代码开始了一个新问题:***.com/q/53069904/5599230

以上是关于无法打开 Windows 命名管道进行写入?的主要内容,如果未能解决你的问题,请参考以下文章

通过重叠 IO 的异步命名 Windows 管道通信

我可以在 Linux 上打开命名管道以在 Python 中进行非阻塞写入吗?

程序打开同一个命名管道并用 C 多次写入

Windows 命名管道无法正确响应并发请求

在 bash 中打开命名管道,而不读取或写入它

无法在 Windows 7 中的命名管道内创建进程