命名管道:ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE
Named pipe: ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE
我重新激活了我确定在几个月前使用过的代码。它让我发疯,但它不再是了。我在其他问题中找不到答案。
在服务器端,我使用
创建了一个管道
#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
在服务器上然后 returns 与 TRUE
和 GetLastError == 0
。但是当它试图调用 ReadFile
来读取管道上的传入数据时,ReadFile
立即 returns FALSE
和 GetLastError==ERROR_BROKEN_PIPE
。
在客户端,CreateFile
返回了 GetLastError==231
、"All pipe instances are busy"。虽然它是唯一的客户!调用 WaitNamedPipe(pipe, 2000)
returns,错误代码为 121,"The semaphore timeout period has expired"。
在 CreateNamedPipe
中增加允许的客户端数量不会改变任何内容。
在客户端尝试连接的那一刻,管道似乎完全坏了。但为什么?客户端和服务器 运行 在同一台机器上,具有相同的用户甚至相同的会话。
然后对 ConnectNamedPipe
的另一个调用失败,GLE=232:"The pipe is being closed".
我还有其他 SECURITY_ATTRIBUTES
用于 CreateNamedPipe
,它允许非提升用户连接,但这没有区别。
我也尝试在客户端上使用 CallNamedPipe
结果相同。
PathFileExists 是管道杀手!经过几个小时的尝试,我终于找到了破坏管道的原因:对管道名称上的 PathFileExists 进行简单调用!这是最近在客户端添加的,用于检查管道是否已经创建。我查看了代码更改,但我完全错过了。 PathFileExists 正确 returns true 或 false 但似乎弄乱了管道(正如我所说的那样,它对允许多个客户端连接没有帮助)。啊!!!
我重新激活了我确定在几个月前使用过的代码。它让我发疯,但它不再是了。我在其他问题中找不到答案。
在服务器端,我使用
创建了一个管道#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
在服务器上然后 returns 与 TRUE
和 GetLastError == 0
。但是当它试图调用 ReadFile
来读取管道上的传入数据时,ReadFile
立即 returns FALSE
和 GetLastError==ERROR_BROKEN_PIPE
。
在客户端,CreateFile
返回了 GetLastError==231
、"All pipe instances are busy"。虽然它是唯一的客户!调用 WaitNamedPipe(pipe, 2000)
returns,错误代码为 121,"The semaphore timeout period has expired"。
在 CreateNamedPipe
中增加允许的客户端数量不会改变任何内容。
在客户端尝试连接的那一刻,管道似乎完全坏了。但为什么?客户端和服务器 运行 在同一台机器上,具有相同的用户甚至相同的会话。
然后对 ConnectNamedPipe
的另一个调用失败,GLE=232:"The pipe is being closed".
我还有其他 SECURITY_ATTRIBUTES
用于 CreateNamedPipe
,它允许非提升用户连接,但这没有区别。
我也尝试在客户端上使用 CallNamedPipe
结果相同。
PathFileExists 是管道杀手!经过几个小时的尝试,我终于找到了破坏管道的原因:对管道名称上的 PathFileExists 进行简单调用!这是最近在客户端添加的,用于检查管道是否已经创建。我查看了代码更改,但我完全错过了。 PathFileExists 正确 returns true 或 false 但似乎弄乱了管道(正如我所说的那样,它对允许多个客户端连接没有帮助)。啊!!!