BOOL TransactNamedPipe(HANDLE hNamedPipe, LPVOID lpWriteBuf, DWORD cbWriteBuf, LPVOID lpReadBuf, DWORD cbReadBuf, LPDWORD lpcbRead, LPOVERLAPPED lpOverlapped)
Смысл всех параметров здесь должен быть ясен, поскольку данная функция сочетает в себе функции WriteFile и ReadFile, применяемые к дескриптору именованного канала. Указываются как выходной, так и входной буфер, а разыменованный указатель lpcbRead предоставляет размер сообщения. Перекрывающиеся операции (глава 14) возможны, однако в более типичных случаях функция ожидает ответа.
Функция TransactNamedPipe удобна в использовании, однако, как показывает рис. 11.2, она требует создания постоянного соединения, что ограничивает число возможных клиентов[32].
Ниже приводится прототип второй клиентской вспомогательной функции.
BOOL CallNamedPipe(LPCTSTR lpPipeName, LPVOID lpWriteBuf, DWORD cbWriteBuf, LPVOID lpReadBuf, DWORD cbReadBuf, LPDWORD lpcbRead, DWORD dwTimeOut)
Функция CallNamedPipe не требует образования постоянного соединения; вместо этого она создает временное соединение, объединяя в себе выполнение следующей последовательности операций:
CreateFile
WriteFile
ReadFile
CloseHandle
Преимуществом такого способа является лучшее использование канала за счет снижения накладных расходов системных ресурсов на один запрос.
Смысл параметров этой функции тот же, что и в случае функции TransactNamedPipe, если не считать того, что вместо дескриптора для указания канала используется его имя. Функция CallNamedPipe выполняется синхронном режиме (отсутствует структура OVERLAPPED). Указываемая при ее вызове длительность периода ожидания (dwTimeOut) (в миллисекундах) относится к соединению, а не транзакции. Параметр dwTimeOut имеет три специальных значения:
• NMPWAIT_NOWAIT
• NMPWAIT_WAIT_FOREVER
• NMPWAIT_USE_DEFAULT_WAIT, которое приводит к использованию интервала ожидания по умолчанию, заданного в вызове функции CreateNamedPipe.
В дополнение к возможности чтения данных из именованного канала с помощью функции ReadFile можно также определить, имеются ли в канале фактические сообщения, используя для этого функцию PeekNamedPipe. Это средство может быть использовано для опроса именованного канала (неэффективная операция), определения размера сообщения, чтобы распределить память для буфера перед выполнением чтения, или просмотра поступающих сообщений с целью назначения им приоритетов для последующей обработки.
BOOL PeekNamedPipe(HANDLE hPipe, LPVOID lpBuffer, DWORD cbBuffer, LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage)
Функция PeekNamedPipe обеспечивает считывание любого байта или сообщения из канала без их удаления, но ее невозможно блокировать, и она осуществляет возврат сразу же по завершении выполнения.
Чтобы определить, имеются ли в канале данные, необходимо проверить значение *lpcbAvail; если данные в канале присутствуют, оно должно быть больше 0. В этом случае параметры lpBuffer и lpcbRead могут иметь значения NULL. Если же буфер определен параметрами lpBuffer и cbBuffer, то значение *lpcbMessage укажет вам, остается ли еще некоторое количество байтов сообщений, которые не умещаются в буфере, что позволяет распределять буфер большего размера, прежде чем осуществлять чтение из именованного канала. Для канала, работающего в режиме считывания байтов, это значение равно 0.
Следует помнить, что функция PeekNamedPipe осуществляет чтение, не уничтожая данные, и поэтому для удаления сообщений или байтовых данных из канала требуется последующее применение функции ReadFile.