命名管道:ConnectNamedPipe 返回 ERROR_BROKEN_PIPE 后的 ReadFile

use*_*157 3 c++ windows winapi named-pipes server

我重新激活了几个月前我确信可以使用的代码。它让我发疯,但现在不再了。我在其他问题中找不到答案。

在服务器端,我使用创建一个管道

#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));
Run Code Online (Sandbox Code Playgroud)

然后一个线程等待传入的客户端ConnectNamedPipeConnectNamedPipe阻塞直到客户端连接

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 
Run Code Online (Sandbox Code Playgroud)

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

当客户端尝试连接时,管道似乎完全损坏了。但为什么?客户端和服务器都运行在同一台机器上,具有相同的用户甚至相同的会话。另一个调用ConnectNamedPipethen 失败,GLE=232:“管道正在关闭”。

我还有其他SECURITY_ATTRIBUTESfor CreateNamedPipe,它允许非提升用户连接,但这没有什么区别。

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

use*_*157 5

PathFileExists 是管道杀手!经过几个小时的尝试,我终于找到了破坏管道的原因:对管道名称上的 PathFileExists 的简单调用!这是最近在客户端添加的,用于检查管道是否已创建。我查看了代码更改,但我完全错过了。PathFileExists 正确返回 true 或 false,但似乎弄乱了管道(正如我所说,它对允许多个客户端连接没有帮助)。啊啊!!!