Проблема именованного канала Windows: код ошибки 233 - PullRequest
8 голосов
/ 15 декабря 2010

Мне нужна помощь в подаче заявления.Это простая программа, которая реагирует на параметры командной строки.Если приложение вызывается впервые, оно запускается как конвейерный сервер (блокирующий, не перекрывающийся) в другом потоке, выделенном для него, в то время как основной поток делает что-то еще.Теперь пользователь может по-прежнему вызывать приложение, используя те же параметры исполняемого файла приложения и командной строки, но, поскольку это не первый экземпляр приложения, он передает параметры командной строки в первый экземпляр, используя канал, а затем убивает себя.Итак, это похоже на одноэлементный процесс в шаблонах-lingo.

В идеале, это должно быть так:

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.

Теперь моя единственная проблема в том, что когда я делаю вышеуказанные строки, это происходит:

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

Код моего конвейерного сервера выглядит примерно так (псевдокод):

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 );

Версия моего клиента выглядит так (псевдокод):

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

Согласно MSDN, если сервер использует DisconnectNamedPipe (), клиент принудительно отключается, и при следующей попытке клиента он получит ошибку.Как вы думаете, в этом причина?Если так, как я могу отключить клиента без дополнительной ошибки?Иначе, что я должен знать, чтобы заставить эту работу ???Потратил много часов, чтобы понять это.

1 Ответ

11 голосов
/ 18 декабря 2010

Вы должны обрабатывать связь с каждым клиентским экземпляром на другом серверном экземпляре канала, используя отдельный поток для каждого.Поэтому, когда ConnectNamedPipe() возвращается, немедленно создайте новый поток слушателя, чтобы дождаться следующего клиента, прежде чем обрабатывать сообщение от только что подключенного клиента.

Каждый клиент будет тогда говорить через только что созданный экземплярканал, и вы не увидите ошибок ERROR_PIPE_NOT_CONNECTED.

т.е. псевдо-код примерно так:

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
    }
}
...