命名管道无法第二次连接
Named pipe can't connect for second time
我有一个客户端-服务器管道进程,当我第一次尝试连接时,一切正常,但是当我再次启动我的客户端进程而不重新启动服务器时,我无法连接并出现 PIPE_BUSY 错误,虽然 GetOverlappedResult 在服务器上成功,但 waitforsingleobject 并不表示有人连接,消息当然是空的。
std::wstring buffer;
while (true) {
// pinging here...
DWORD result = WaitForSingleObject(hEvent, 2000);
if (result == WAIT_FAILED) {
std::wcout << result << std::endl;
break;
}
if (result == WAIT_TIMEOUT) {
// always here
}
ResetEvent(hEvent);
DWORD bytesTransferred;
OVERLAPPED ov;
ZeroMemory( & ov, sizeof(OVERLAPPED));
ov.hEvent = hEvent;
if (GetOverlappedResult(pipe(), & ov, & bytesTransferred, TRUE) == 0) // FAILED
{
return; // we do never get here...
} else {
ZeroMemory( & ov, sizeof(OVERLAPPED));
DWORD bytesToRead = 0;
BOOL pingPipe;
Timer timer(1000);
while (!bytesToRead || !pingPipe) {
if (!timer.in()) {
break;
}
pingPipe = PeekNamedPipe(pipe(), NULL, 0, NULL, & bytesToRead, NULL);
}
buffer.resize(sizeof(TCHAR) * bytesToRead);
if (!ReadFile(pipe(), & buffer[0], bytesToRead, & bytesTransferred, & ov) && timer.in()) {
if (GetLastError() == ERROR_IO_PENDING) {
continue;
}
return;
}
// data here
std::wcout << buffer << std::endl;
}
}
DisconnectNamedPipe(pipe());
我无法准确地说出 hEvent
是什么,因为您遗漏了所有初始化代码,但您使用的 GetOverlappedResult
不正确,并且所有的赌注在这一点上都差不多:
OVERLAPPED ov;
ZeroMemory( & ov, sizeof(OVERLAPPED));
ov.hEvent = hEvent;
if (GetOverlappedResult(pipe(), & ov, & bytesTransferred, TRUE) == 0) ...
这不是你的做法。您不会声明 OVERLAPPED
并将其全新传递给 GetOverlappedResult
。您实际上必须 开始 重叠操作(读取、写入、连接等),例如首先将 OVERLAPPED
传递给 ReadFile
或其他东西。你给它的事件句柄通常是你创建的一个事件,它 专用于 那个重叠的任务,而不是其他任何东西也在使用的事件。
这相当于你在街上走到一个随机的陌生人面前,突然说 "So, did you get that thing I asked for?"。
您正在尝试完成尚未开始的重叠操作,并且您使用的事件句柄可能也用于检查传入连接或其他内容。所以接下来会发生什么还悬而未决。
所以你有两个选择:
- 阅读this tutorial (which I haven't verified for correctness but at a glance it looks fine), this overview of overlapped I/O, and the MS example of named pipe servers with overlapped I/O,然后再读一遍直到你理解为止,或者
- 停止使用重叠 I/O。这是我现在推荐的,只是为了理解概念。
除上述问题外,您的客户端可能还有其他问题,但您没有显示相关代码。您可能需要根据相关文档仔细检查它,以确保在那一端一切正常。此外,就缺少代码而言,您需要通过在创建时传递适当的标志来验证您是否在服务器端以重叠模式创建管道(无法在 phone 上查找编辑,但检查管道创建 api 文档)。
我有一个客户端-服务器管道进程,当我第一次尝试连接时,一切正常,但是当我再次启动我的客户端进程而不重新启动服务器时,我无法连接并出现 PIPE_BUSY 错误,虽然 GetOverlappedResult 在服务器上成功,但 waitforsingleobject 并不表示有人连接,消息当然是空的。
std::wstring buffer;
while (true) {
// pinging here...
DWORD result = WaitForSingleObject(hEvent, 2000);
if (result == WAIT_FAILED) {
std::wcout << result << std::endl;
break;
}
if (result == WAIT_TIMEOUT) {
// always here
}
ResetEvent(hEvent);
DWORD bytesTransferred;
OVERLAPPED ov;
ZeroMemory( & ov, sizeof(OVERLAPPED));
ov.hEvent = hEvent;
if (GetOverlappedResult(pipe(), & ov, & bytesTransferred, TRUE) == 0) // FAILED
{
return; // we do never get here...
} else {
ZeroMemory( & ov, sizeof(OVERLAPPED));
DWORD bytesToRead = 0;
BOOL pingPipe;
Timer timer(1000);
while (!bytesToRead || !pingPipe) {
if (!timer.in()) {
break;
}
pingPipe = PeekNamedPipe(pipe(), NULL, 0, NULL, & bytesToRead, NULL);
}
buffer.resize(sizeof(TCHAR) * bytesToRead);
if (!ReadFile(pipe(), & buffer[0], bytesToRead, & bytesTransferred, & ov) && timer.in()) {
if (GetLastError() == ERROR_IO_PENDING) {
continue;
}
return;
}
// data here
std::wcout << buffer << std::endl;
}
}
DisconnectNamedPipe(pipe());
我无法准确地说出 hEvent
是什么,因为您遗漏了所有初始化代码,但您使用的 GetOverlappedResult
不正确,并且所有的赌注在这一点上都差不多:
OVERLAPPED ov;
ZeroMemory( & ov, sizeof(OVERLAPPED));
ov.hEvent = hEvent;
if (GetOverlappedResult(pipe(), & ov, & bytesTransferred, TRUE) == 0) ...
这不是你的做法。您不会声明 OVERLAPPED
并将其全新传递给 GetOverlappedResult
。您实际上必须 开始 重叠操作(读取、写入、连接等),例如首先将 OVERLAPPED
传递给 ReadFile
或其他东西。你给它的事件句柄通常是你创建的一个事件,它 专用于 那个重叠的任务,而不是其他任何东西也在使用的事件。
这相当于你在街上走到一个随机的陌生人面前,突然说 "So, did you get that thing I asked for?"。
您正在尝试完成尚未开始的重叠操作,并且您使用的事件句柄可能也用于检查传入连接或其他内容。所以接下来会发生什么还悬而未决。
所以你有两个选择:
- 阅读this tutorial (which I haven't verified for correctness but at a glance it looks fine), this overview of overlapped I/O, and the MS example of named pipe servers with overlapped I/O,然后再读一遍直到你理解为止,或者
- 停止使用重叠 I/O。这是我现在推荐的,只是为了理解概念。
除上述问题外,您的客户端可能还有其他问题,但您没有显示相关代码。您可能需要根据相关文档仔细检查它,以确保在那一端一切正常。此外,就缺少代码而言,您需要通过在创建时传递适当的标志来验证您是否在服务器端以重叠模式创建管道(无法在 phone 上查找编辑,但检查管道创建 api 文档)。