Windows命名管道问题:错误代码233备用

问题描述:

我在我正在申请的应用程序上需要帮助.这是一个响应命令行参数的简单程序.如果是第一次调用该应用程序,则它将在专用于它的另一个线程上作为管道服务器(阻塞,非重叠)启动,而主线程会执行其他操作.现在,用户仍然可以使用相同的应用程序可执行文件和命令行参数来调用该应用程序,但是由于它不是应用程序的第一个实例,因此它使用管道将命令行参数传递给第一个实例,然后终止自身.因此,这就像是模式语言中的单例过程.

I need help on my application I am making. It's a simple program that responds to command line parameters. If the application is invoked for the first time, it starts up as a pipe server (blocking, non-overlapped) on another thread devoted to it, while the main thread does something else. Now, the user can still invoke the application using the same application executable and command line parameters but since its not the first instance of the application, it passes the command line parameters to the first instance using the pipe, then kills the itself. So, it's like a singleton process in patterns-lingo.

理想情况下,应该像这样:

Ideally, it should be like this:

app.exe "first"    // starts app.exe as a pipe server and prints "first"
app.exe "second"   // client process causes server instance to print "second"
app.exe "third"    // client process causes server instance to print "third"
app.exe "fourth"   // client process causes server instance to print "fourth"
app.exe "fifth"    // client process causes server instance to print "fifth"
app.exe -quit      // client process causes server instance to terminate.

现在,我唯一的问题是,当我进行上述操作时,会发生这种情况:

Now, my only problem is, when I do the above lines this happens:

app.exe "first"    // starts app.exe as a pipe server and prints "first"
app.exe "second"   // client process returns a GetLastError code of 233
app.exe "third"    // client process causes server instance to print "third"
app.exe "fourth"   // client process returns a GetLastError code of 233
app.exe "fifth"    // client process causes server instance to print "fifth"
app.exe -quit      // client process returns a GetLastError code of 233

我的管道服务器代码如下(伪代码):

My pipe server code goes something like this (pseudo code):

CreateNamedPipe();
// Code below now runs on a separate thread...
while( !Quit )
{
    if( ConnectNamedPipe() is successful )
    {
        if( PeekNamedPipe() has a message )
        {
            ReadFile();
            ProcessReceivedMessage();
        }
        FileFlushBuffers();
        DisconnectNamedPipe();
    }
}
CloseHandle( the pipe );

我的客户端版本如下(伪代码):

My client version goes like this (pseudo code):

if( WaitNamedPipe( FOREVER ) != 0 )
{
    GetParametersAndFormAMessage();
    CreateFile();
    WriteFile(); // Sends message to the pipe server
}
CloseHandle();

根据MSDN,如果服务器使用DisconnectNamedPipe(),则客户端将被强制断开连接,并且在客户端的下一次尝试时,它们将收到错误消息.你认为那是原因吗?如果是这样,如何在没有发生额外错误的情况下断开客户端连接?否则,我应该知道的一切才能使这项工作成功???花了很多时间来解决这个问题.

According to MSDN, if the server uses DisconnectNamedPipe(), the client is forced disconnected and on the next attempt of the client, they will get an error. Do you think that's the reason? If so, how do I disconnect a client without that extra error happening? Otherwise, anything I should know to make this work??? Spent a lot of hours figuring this out.

您应该在管道的不同服务器端实例上处理与每个客户端实例的通信,并为每个客户端实例使用单独的线程.因此,当ConnectNamedPipe()返回时,立即处理新的侦听器线程以等待下一个客户端,然后再处理来自刚刚连接的客户端的消息.

You should handle communication with each client instance on a different server-side instance of the pipe, using a separate thread for each. So, when ConnectNamedPipe() returns, immediately spawn a new listener thread to wait for the next client, before processing the message from the client which just connected.

然后,每个客户端将通过新创建的管道实例进行交谈,并且您不会看到ERROR_PIPE_NOT_CONNECTED错误.

Each client will then be talking via a freshly created instance of the pipe, and you won't see the ERROR_PIPE_NOT_CONNECTED errors.

即伪代码是这样的:

Main Thread
{
    CreateListenerThread();
    WaitForQuitEvent();
}

ListenerThread
{
    ConnectNamedPipe();
    if (no error)
    {
        CreateListenerThread();
        if( PeekNamedPipe() has a message )
        {
            ReadFile();
            ProcessReceivedMessage(); // if -quit signal quit event
        }
        FileFlushBuffers();
        DisconnectNamedPipe();
        CloseHandle();
    }
    else
    {
        // handle/report error
    }
}