Я начинаю с именованных каналов и должен использовать их для IPC между двумя локальными процессами. У меня есть и сервер, и клиентский процесс, использующий канал в режиме перекрытия без блокировки.
Все работает нормально (сервер успешно получает строку, отправленную клиентом), за исключением того, что событие, переданное ConnectNamedPipe () через структуру OVERLAPPED, не получает сигнал, как ожидалось (сигнал при подключении клиента).
В то время как сервер заблокирован при вызове WaitForSingleObject (), клиентский процесс, подключенный к каналу, отправил свои данные и завершился, но событие не получает сигнал. Что мне не хватает?
Код сервера:
HANDLE hPipe = ::CreateNamedPipeW(
L"\\\\.\\pipe\\ThePipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
1,
4096,
4096,
100,
nullptr);
OVERLAPPED ov = {0};
ov.hEvent = ::CreateEventW(nullptr, TRUE, FALSE, nullptr);
BOOL retVal = ::ConnectNamedPipe(hPipe, &ov);
if (retVal == 0)
{
DWORD err = ::GetLastError();
if (err == ERROR_IO_PENDING)
{
::WaitForSingleObject(ov.hEvent, 30000);
}
if (err == ERROR_PIPE_LISTENING)
{
::WaitForSingleObject(ov.hEvent, 30000); // this blocks until time-out???
}
}
Вы не должны использовать (не рекомендуется) PIPE_NOWAIT
вместе с перекрывающимся режимом. PIPE_NOWAIT
марки ConnectNamedPipe
немедленно вернуться ERROR_PIPE_LISTENING
если клиент не подключен; перекрывающийся ввод-вывод просто не происходит, и ожидание события бесполезно.
Либо вы установили PIPE_NOWAIT
и периодически опрашивать канал до успеха, или вы установите FILE_FLAG_OVERLAPPED
и использовать событие, чтобы проверить / дождаться завершения.
Других решений пока нет …