ConnectNamedPipe后命名管道:ReadFile返回ERROR_BROKEN_PIPE

时间:2016-03-16 13:46:08

标签: c++ windows winapi server named-pipes

我重新激活了几个月前我确定曾经工作过的代码。它让我发疯,但现在已经不复存在了。我在其他问题上找不到答案。

在服务器端,我使用

创建管道
#define MAX_MESSAGE_LENGTH 1024
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE);

sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;

auto pipe_name = _T("\\\\.\\pipe\\") + _serviceName;

HANDLE pipe = CreateNamedPipe(
    pipe_name.c_str(),
    PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
    1, 
    MAX_MESSAGE_LENGTH, MAX_MESSAGE_LENGTH, // buffer lengths (advisory)
    0, // default timeout of 50ms when WaitNamedPipe uses NMPWAIT_USE_DEFAULT_WAIT
    &sa));

然后一个线程等待ConnectNamedPipe的传入客户端。 ConnectNamedPipe阻止,直到客户端与

连接
HANDLE pipe = CreateFile(
    pipe_name.c_str(),   // pipe name 
    GENERIC_READ |  // read and write access 
    GENERIC_WRITE,
    0,              // no sharing 
    NULL,           // default security attributes
    OPEN_EXISTING,  // opens existing pipe 
    FILE_ATTRIBUTE_NORMAL, // default attributes 
    NULL);         // no template file 
然后,服务器上的

ConnectNamedPipe将返回TRUEGetLastError == 0。但是当它试图调用ReadFile来读取管道上的传入数据时,ReadFile会立即返回FALSEGetLastError==ERROR_BROKEN_PIPE。 在客户端,CreateFile已返回GetLastError==231,“所有管道实例都忙”。虽然它是唯一的客户!对WaitNamedPipe(pipe, 2000)的调用将返回错误代码121,“信号量超时期限已过期”。 增加CreateNamedPipe中允许的客户端数量不会改变任何内容。

在客户端尝试连接的那一刻,管道似乎完全被破坏了。但为什么?客户端和服务器在同一台机器上运行,具有相同的用户甚至同一会话。 然后对ConnectNamedPipe的另一次调用因GLE = 232而失败:“管道正在关闭”。

我还为SECURITY_ATTRIBUTES提供了其他CreateNamedPipe,这将允许非提升用户进行连接,但这没有任何区别。

此外,我尝试在客户端上使用CallNamedPipe,结果相同。

1 个答案:

答案 0 :(得分:3)

PathFileExists是管道杀手!经过几个小时的尝试后,我终于找到了破坏管道的东西:在管道名称上简单调用PathFileExists!最近在客户端添加了此项以检查管道是否已创建。我看了一下代码更改,但我完全错过了。 PathFileExists正确返回true或false但似乎搞乱了管道(因为我告诉它不允许多个客户端连接)。哎呀!