无法打开 Windows 命名管道进行写入?
Can't open Windows Named Pipe for writing?
我不明白为什么我什至不能打开我在另一个进程中创建的用于写入的命名管道。
我收到错误
231 (All pipe instances are busy).
作者(客户):
#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;
}
reader(服务器)之前创建过这样的管道(注意 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
读取或者发送超时。
CreateNamedPipe
的第 4 个参数 - nMaxInstances
- 这是 可以为此管道创建的最大实例数。
所以这不是单次调用创建的实例数,而是可以创建的最大实例数。对 CreateNamedPipe
的单次调用总是创建一 (1) 个管道实例。如果你想要 4 个实例 - 你需要调用 CreateNamedPipe
4 次。最初也是在监听状态下创建的管道,因此客户端可以通过调用 CreateFile
连接到它。但是在连接断开后(因为客户端关闭了自己的句柄)并且你想接受同一个管道实例的新客户端连接 - 你需要调用 DisconnectNamedPipe
然后 ConnectNamedPipe
- 只有在这个新客户端可以再次连接到相同的管道实例。
但无论如何,即使您只创建单个管道实例,通过一次调用 CreateNamedPipeA
- 第一个客户端可以连接到它。错误 231 - 我猜真正的错误来源是 STATUS_PIPE_NOT_AVAILABLE
( 命名管道的实例不能
在监听状态下发现 ) - 你可以在 CreateFile
失败后通过调用 RtlGetLastNtStatus()
检查这个而不是 GetLastError()
说管道名称是有效的,访问没有问题,但是有人已经连接(可能已经断开连接)到管道 - 永远不要首先调用 CreateFile
return 这个错误
我不明白为什么我什至不能打开我在另一个进程中创建的用于写入的命名管道。
我收到错误
231 (All pipe instances are busy).
作者(客户):
#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;
}
reader(服务器)之前创建过这样的管道(注意 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
读取或者发送超时。
CreateNamedPipe
的第 4 个参数 - nMaxInstances
- 这是 可以为此管道创建的最大实例数。
所以这不是单次调用创建的实例数,而是可以创建的最大实例数。对 CreateNamedPipe
的单次调用总是创建一 (1) 个管道实例。如果你想要 4 个实例 - 你需要调用 CreateNamedPipe
4 次。最初也是在监听状态下创建的管道,因此客户端可以通过调用 CreateFile
连接到它。但是在连接断开后(因为客户端关闭了自己的句柄)并且你想接受同一个管道实例的新客户端连接 - 你需要调用 DisconnectNamedPipe
然后 ConnectNamedPipe
- 只有在这个新客户端可以再次连接到相同的管道实例。
但无论如何,即使您只创建单个管道实例,通过一次调用 CreateNamedPipeA
- 第一个客户端可以连接到它。错误 231 - 我猜真正的错误来源是 STATUS_PIPE_NOT_AVAILABLE
( 命名管道的实例不能
在监听状态下发现 ) - 你可以在 CreateFile
失败后通过调用 RtlGetLastNtStatus()
检查这个而不是 GetLastError()
说管道名称是有效的,访问没有问题,但是有人已经连接(可能已经断开连接)到管道 - 永远不要首先调用 CreateFile
return 这个错误