2017-02-15 14 views
0

У меня есть процессы клиент-сервер, и когда я пытаюсь подключиться в первый раз, все в порядке, но когда я снова запускаю свой клиентский процесс, не перезагружая сервер, я не могу подключиться с ошибкой 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()); 
+0

В вашем сообщении отсутствует код ключа (который я предполагаю, это фрагмент случайного бита конца серверной части?). Пожалуйста, создайте и опубликуйте [полный пример] (http://sscce.org/). При этом вы можете обнаружить эту проблему, но по минимуму вы предоставите необходимую информацию для других, чтобы помочь. –

+0

вызов 'GetOverlappedResult' убивает асинхронную логику – RbMm

+0

Это говорит о том, что я подозреваю ваше непонимание« GetOverlappedResult », и ваша случайная упаковка вашей структуры« OVERLAPPED »с« hEvent »является основной проблемой, а также вы фактически не запускаете надлежащую операцию перекрытия (вы не просто заполняете свой собственный «OVERLAPPED», вы должны получить его, например, с помощью «ReadFile», который заполнит дескриптор события и такой * для * вас), где событие, по-видимому, запускается при входящем соединении, фактически блокируя «GetOverlappedResult», пока кто-то не попытается подключиться или что-то в этом роде. –

ответ

1

Я не могу точно сказать, что hEvent это, так как вы оставили всю ваш код инициализации, но вы используете GetOverlappedResult неправильно, и все ставки в значительной степени от в этой точке:

OVERLAPPED ov; 
ZeroMemory(& ov, sizeof(OVERLAPPED)); 
ov.hEvent = hEvent; 

if (GetOverlappedResult(pipe(), & ov, & bytesTransferred, TRUE) == 0) ... 

Это не то, как вы это делаете. Вы не объявляете OVERLAPPED и передаете его от нового до GetOverlappedResult. Вы должны на самом деле начать операцию перекрытия (чтение, запись, соединение, что угодно), например. передавая OVERLAPPED в ReadFile или что-то в первую очередь. И обработчик события, который вы ему даете, как правило, представляет собой событие, которое вы создали, это , посвященный для этой наложенной задачи, а не тот, который также используется любым другим.

Это эквивалент того, что вы подходите к случайному незнакомому человеку на улице и говорите, из ниоткуда: «Итак, вы получили то, о чем я просил?».

Вы пытаетесь выполнить операцию перекрытия, которую вы еще не запускали, и используете дескриптор события, который, как предполагается, также используется для проверки входящих соединений или чего-то еще. Так что в воздухе все в порядке, что произойдет.

Так у вас есть два варианта:

  1. Read this tutorial (который я не проверял правильность, но на первый взгляд она выглядит хорошо), this overview of overlapped I/O и the MS example of named pipe servers with overlapped I/O, а затем прочитать все это снова, пока вы не поймете его , или
  2. Остановить использование перекрытых входов/выходов. Это то, что я рекомендую на данный момент просто для того, чтобы убрать эти понятия.

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

+0

Обратите внимание, что если вы начнете перекрывающуюся операцию, немедленно перейдите к GetOverlappedResult, не делая ничего другого между ними, вы также можете не использовать перекрывающийся IO и сохранить себе сложность. Это очень полезно, когда вам нужна асинхронность, но если вам не нужна простая синхронная операция. –