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

时间:2015-07-29 12:09:18

标签: 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);
...

然而,当我尝试重新打开管道以读取CreateFile时,调用失败,并且#34;所有管道都忙。&#34;

我在这里缺少什么?

修改 偷看工作正常,即

DWORD nRead, nTotal, nLeft;
PeekNamedPipe(hPipe, buffRead, buffLength, &nRead, &nTotal, &nLeft);

正确返回书面数据。

REMARK。 这是更大的概念的证明。不会涉及新的线程和流程。

3 个答案:

答案 0 :(得分:2)

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

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

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

(注意每个管道实例有两端;服务器端和客户端.AdigNamedPipe的句柄总是到服务器端,CreateFile的句柄总是到客户端。写入服务器端的数据只能从客户端读取,反之亦然。)

答案 1 :(得分:1)

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

  1. 服务器使用CreateNamedPipe函数创建命名管道;
  2. 服务器开始使用ConnectNamedPipe方法等待客户端连接;
  3. 客户端使用CreateFile API调用创建管道的一面;
  4. 服务器和客户端使用ReadFile/WriteFile;
  5. 进行通信
  6. 管道已关闭DisconnectNamedPipe,可以使用ConnectNamedPipe重新启用。
  7. 您可以在MSDN here中看到完整的示例。

答案 2 :(得分:0)

这是因为管道的两端都已经打开(*)......

首先使用CreatePipe调用打开,另一个使用第一个CreateFile调用。您不应该尝试再打开一次管道,而只需从hPipe HANDLE中读取:

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);

ReadFile(hPipe, buffRead, buffLength, &nRead, 0); // nRead=9, buffRead="SOME TEXT"
...

(*)您确实为PIPE_UNLIMITED_INSTANCES调用中的nMaxInstances参数指定了CreateNamedPipe,但由于您从未调用ConnectNamedPipe来创建其他端点,因此只有一个{{1}被允许。