2017-02-15 52 views
0

У меня есть эта часть кода, которая представляет собой простой сервер труб. Когда я устанавливаю атрибут PIPE_NOWAIT, а затем пытаюсь подключиться к нему с клиентом с помощью функции CreateFile - ничего не происходит, мы все еще находимся во втором блоке. Когда я удаляю флаг PIPE_NOWAIT - мы входим в функцию ConnectNamedPipe и после того, как CreateFile был вызван от клиента, мы попадаем в первый блок, что означает, что мы преуспели. Почему так?PIPE_NOWAIT breaks connetion

HANDLE hPipe; 
std::string msg; 
DWORD dwRead; 

hPipe = CreateNamedPipe(L"\\\\.\\pipe\\Pipe100500", 
    PIPE_ACCESS_DUPLEX, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists... 
    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT, 
    1, 
    1024 * 16, 
    1024 * 16, 
    NMPWAIT_USE_DEFAULT_WAIT, 
    NULL); 

while (true) 
{ 
    if (ConnectNamedPipe(hPipe, NULL) != FALSE) 
    { 
     // Waiting in the ConnectNamedPipe and then we are here 
    } 
    else 
    { 
     // always here when PIPE_NOWAIT 
    } 
} 
+0

почему вы используете 'PIPE_NOWAIT'? вам нужно использовать 'FILE_FLAG_OVERLAPPED' – RbMm

+0

Почему я не могу это сделать? – banana36

+0

'PIPE_NOWAIT' -'Примечание о том, что неблокирующий режим поддерживается для совместимости с Microsoft LAN Manager версии 2.0 и не должен использоваться для достижения асинхронного ввода-вывода с именованными каналами.' Если вы хотите асинхронный ввод-вывод - используйте 'FILE_FLAG_OVERLAPPED' – RbMm

ответ

0

За документацию CreateNamedPipe():

PIPE_NOWAIT
0x00000001

режим неблокирования включен. В этом режиме ReadFile, WriteFile и ConnectNamedPipe всегда немедленно возвращается.

За документацию ConnectNamedPipe():

Если указанная ручка труба находится в неблокируемом режиме, ConnectNamedPipe всегда возвращается немедленно. В неблокирующем режиме ConnectNamedPipe возвращает ненулевое значение при первом вызове для экземпляра канала, который отключен от предыдущего клиента. Это означает, что теперь канал доступен для подключения к новому клиентскому процессу. Во всех других ситуациях, когда ручка трубы находится в неблокирующем режиме, ConnectNamedPipe возвращает ноль. В этих ситуациях GetLastError возвращает ERROR_PIPE_LISTENING, если клиент не подключен, ERROR_PIPE_CONNECTED, если клиент подключен, и ERROR_NO_DATA, если предыдущий клиент закрыл свой дескриптор канала, но сервер не отключился. Обратите внимание, что хорошее соединение между клиентом и сервером существует только после получения ошибки ERROR_PIPE_CONNECTED.

Примечание. Режим неблокировки поддерживается для совместимости с Microsoft LAN Manager версии 2.0 и не должен использоваться для достижения асинхронного ввода и вывода (I/O) с именованными каналами.

Таким образом, чтобы правильно использовать PIPE_NOWAIT (даже если вы действительно не должны использовать его на всех!), Вам нужно будет что-то еще вроде этого:

HANDLE hPipe; 
std::string msg; 
DWORD dwRead; 

hPipe = CreateNamedPipe(L"\\\\.\\pipe\\Pipe100500", 
    PIPE_ACCESS_DUPLEX, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists... 
    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT, 
    1, 
    1024 * 16, 
    1024 * 16, 
    NMPWAIT_USE_DEFAULT_WAIT, 
    NULL); 

if (hPipe != INVALID_HANDLE_VALUE) 
{ 
    while (true) 
    { 
     if (ConnectNamedPipe(hPipe, NULL)) 
     { 
      // pipe has been disconnected and is now available to be connected to again... 
     } 
     else 
     { 
      switch (GetLastError()) 
      { 
       case ERROR_PIPE_LISTENING: 
        // no client is connected... 
        break; 

       case ERROR_PIPE_CONNECTED: 
        // a client is now connected... 
        break; 

       case ERROR_NO_DATA: 
        // a previous client has closed its pipe handle but the server has not disconnected yet... 
        DisconnectNamedPipe(hPipe); 
        break; 

       default: 
        // fatal error... 
        break; 
      } 
     } 
    } 
} 

В противном случае, делать то, что сказано в документации и не использовать PIPE_NOWAIT. Вместо этого используйте Overlapped I/O, если вы не хотите блокировать ConnectNamedPipe(). MSDN приведены примеры, которые:

Named Pipe Server Using Overlapped I/O

Named Pipe Server Using Completion Routines

Смежные вопросы