命名管道上的 WriteFile 有时会返回 ERROR_NO_DATA

Luk*_*ane 5 c++ winapi named-pipes

我有一个 C++ 程序,它正在创建一个命名管道来写入数据。有些客户反映了客户端连接到命名管道但服务器端无法写入数据的情况(带有ERROR_NO_DATA)。

我能找到的任何 MSDN 页面都没有真正解释此错误代码;有人对如何解决这个问题有任何想法吗?或者说是什么原因呢?


开放代码:

ostringstream pipeName;
pipeName << "\\\\.\\pipe\\unique-named-pipe-" << GetCurrentProcessId();

pipeHandle = CreateNamedPipeA(
    pipeName.str().c_str(),              // pipe name
    PIPE_ACCESS_DUPLEX,                  // open mode
    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // pipe mode
    PIPE_UNLIMITED_INSTANCES,            // max instances
    512,                                 // output buffer size
    512,                                 // input buffer size
    0,                                   // use default timeouts
    NULL);                               // security attributes

if (INVALID_HANDLE_VALUE == pipeHandle)
{
    THROW("Failed to create named pipe", GetLastError());
}

cout << "Pipe ready" << endl;

// Wait for a client to connect to the pipe        
BOOL status = ConnectNamedPipe(pipeHandle, NULL);

if (!status)
{
    DWORD lastError = GetLastError();

    if (ERROR_PIPE_CONNECTED != lastError)
    {
        THROW("Failed to wait for client to open pipe", lastError);
    }
    else
    {
        // Ignore, see MSDN docs for ConnectNamedPipe() for details.
    }
}
Run Code Online (Sandbox Code Playgroud)


编写代码:

// response is a std::string
int writeOffset = 0;
int length = response.length();

while ((int) response.length() > writeOffset)
{
    DWORD bytesWritten;

    BOOL status = WriteFile(
        pipeHandle,
        response.c_str() + writeOffset,
        length - writeOffset,
        &bytesWritten,
        NULL);

    if (!status)
    {
        // This sometimes fails with ERROR_NO_DATA, why??
        THROW("Failed to send via named pipe", GetLastError());
    }

    writeOffset += bytesWritten;
}
Run Code Online (Sandbox Code Playgroud)


投掷宏

#define THROW(message, errorCode) \
{ \
    fprintf(stderr, "%s: line: %d file: %s error:0x%x\n", \
            message, __LINE__, __FILE__, errorCode); \
    fflush(stderr); \
    throw message; \
} \
Run Code Online (Sandbox Code Playgroud)

谢谢!

Bre*_*McK 5

查看 WinError.h,其中定义了此错误代码和其他错误代码:

//
// MessageId: ERROR_NO_DATA
//
// MessageText:
//
// The pipe is being closed.
//
#define ERROR_NO_DATA                    232L
Run Code Online (Sandbox Code Playgroud)

听起来客户端已经关闭了管道的末端 - 也许客户端代码认为它已经获得了完整的字符串,关闭了它们的末端,而上面的代码继续尝试写入?

  • MSDN 上没有明确指出,但有一些网页表明此错误也适用于 WriteFile - 以下是 MSDN 中使用它的一些示例代码:http://support.microsoft.com/kb/190351可能想发布客户端代码。客户端如何知道何时关闭管道或何时拥有完整的字符串?这种情况是否发生在循环中的第一次写入时,或者仅发生在第二次或以后的调用时? (2认同)