命名管道无法再次连接

Named pipe can't connect for second time

本文关键字:连接 管道      更新时间:2023-10-16

我有一个客户端服务器的流程,当我第一次尝试连接时,一切都可以,但是当我再次启动客户端过程而不重新启动服务器时,我无法与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。您实际上必须 start 一个重叠的操作(读,写,连接等),例如首先将OVERLAPPED传递给ReadFile或其他东西。事件处理方法通常是您创建的事件,即对重叠任务的专用,而不是其他任何任务。

这相当于您走到街上一个随机的陌生人,说出"所以,你得到了我要的东西吗?"。

您正在尝试完成您尚未启动的重叠操作,并且您正在使用一个事件手柄,大概也使用该操作来检查传入的连接之类的东西。所以这几乎是在空中发生的事情。

所以您有两个选择:

  1. 阅读本教程(我尚未验证正确性,但瞥见它看起来不错),重叠I/O的概述以及带有重叠的I/O的命名管服务器的示例,然后阅读所有内容再一次,直到您理解它或
  2. 停止使用重叠的I/O。这就是我现在建议的只是为了降低概念。

除了上述内容外,您的客户端可能还会出现其他问题,但是您尚未显示为此的代码。您可能需要对相关文档进行仔细检查,以确保此目的一切正常。另外,就丢失的代码而言,您需要通过传递创建时的适当标志来验证服务器端上的管道(无法查找,在此编辑中查看,但请检查管道创建API文档)。