Win32 API 命名管道,所有管道实例都忙

neg*_*ezu 5 c winapi

我正在尝试写入命名管道并读回相同的内容。考虑以下代码片段(为简洁起见,错误处理被剥离):

const char * pipeName = "\\\\.\\pipe\\pipe";
const char * buffWrite = "SOME TEXT";
unsigned buffLength = strlen(buffWrite);
char buffRead[1024];
DWORD nWritten, nRead;

HANDLE hPipe = CreateNamedPipe(pipeName,
PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, 0);

HANDLE hFile = CreateFile(pipeName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
WriteFile(hFile, buffWrite, buffLength, &nWritten, 0);
CloseHandle(hFile);
//the next line fails with >>All pipe instances are busy.<<
hFile = CreateFile(pipeName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
ReadFile(hFile, buffRead, buffLength, &nRead, 0);
...
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试重新打开管道以读取 CreateFile 调用失败并显示“所有管道都忙”时。

我在这里缺少什么?

编辑。 偷看工作正常,即

DWORD nRead, nTotal, nLeft;
PeekNamedPipe(hPipe, buffRead, buffLength, &nRead, &nTotal, &nLeft);
Run Code Online (Sandbox Code Playgroud)

正确返回写入的数据。

评论。 这是对更大事物的概念证明。不会涉及新的线程和进程。

Ari*_*nhh 5

您正在尝试使用命名管道作为某种缓冲区 - 客户端连接到它,放入一些数据,然后断开连接,之后其他客户端连接并检索该数据。这是无效的方法,命名管道就是一个管道,它有两个端——服务器端客户端,服务器和客户端可以通过它进行通信。常见管道使用场景:

  1. 服务器使用CreateNamedPipe函数创建命名管道;
  2. 服务器使用方法开始等待客户端连接ConnectNamedPipe
  3. 客户端使用 API 调用创建其管道一侧CreateFile
  4. 服务器和客户端使用ReadFile/WriteFile;
  5. 管道已通过 关闭DisconnectNamedPipe,并且可以通过 再次重新激活ConnectNamedPipe

您可以在此处的MSDN 中查看完整示例。


Har*_*ton 5

您收到该特定错误代码的原因是您只创建了命名管道的一个实例,并且您已经使用了它。CreateNamedPipe(您可以通过第二次调用来创建新实例,也可以通过调用 来重用现有实例DisconnectNamedPipe。)

但是,根据您的评论,我相信您希望调用 ReadFile 来检索调用 WriteFile 写入的数据,即您需要相同的管道实例,而不是新的管道实例。

为此,请勿打开新句柄。使用现有的句柄,hPipe

(注意,每个管道实例都有两端;服务器端和客户端。CreateNamedPipe 的句柄始终指向服务器端,而 CreateFile 的句柄始终指向客户端。写入服务器端的数据只能是从客户端读取,反之亦然。)