Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпора 97.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
778.75 Кб
Скачать

Использование именованных каналов

Функция CreateNamedPipe создает первый экземпляр именованного канала и возвращает его дескриптор. Также эта функция определяет максимальное количество экземпляров канала и, следовательно, количество клиентов, которых можно обслужи­вать одновременно.

Обычно процесс создания называется сервером. Процессы-клиенты, возможно, работающие на других системах, открывают этот канал с помощью CreateFile.

Создание именованных каналов

Ниже приведена функция CreateNamedPipe.

HANDLE CreateNamedPipe ( LPCTSTR lpszPipeName,

DWQRD fdwOpenMode, DWORD fdwPipeMode,

DWORD nMaxInstances, DWORD cbOutBuf, DWORD cblnBuf,

DWORD dwTimeOut, LPSECURITY_ATTRIBUTES lpsa)

Параметры

lpszPipeName обозначает имя канала в форме: \\.\pipe\[путь]имя-канала

Точка обозначает локальную машину; иначе говоря, создать канал на удаленной машине нельзя.

fdwOpenMode имеет одно из следующих значений:

  • PIPE_ACCESS_DUPLEX — эквивалентно комбинации GENERIC_READ и GENERIC_WRITE;

  • PIPE_ACCESS_INBOUND — направление данных только от клиента к серверу, эквивалентно GENERIC_READ;

  • PIPE_ACCESS_OUTBOUND — эквивалентно GENERIC_WRITE.

Режим также может быть FILE_FLAG_WRITE_THROUGH (не используется для каналов сообщений) и FILE_FLAG_OVERLAPPED.

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

- PIPE_TYPE_BYTE и PIPE_TYPE_MESSAGE, которые взаимно исключают друг друга, указывают, записываются ли данные в канал как поток байтов или как поток сообщений. Для всех экземпляров канала применяется один и тот же тип.

  • PIPE_READMODE_BYTE и PIPE_READMODE_MESSAGE указывают, читаются ли данные как поток байтов или как поток сообщений. Для PIPE_READMODE_MESSAGE необходимо PIPE_TYPE_MESSAGE.

  • PIPE_WAIT и PIPE_NOWAIT определяют, будет ли операция ReadFile блокироваться. Указывайте значение PIPE_WAIT, поскольку для асинхронного ввода-вывода есть способы получше.

nMaxInstances определяет количество экземпляров канала и, следовательно, ко­личество одновременно обслуживаемых клиентов. Если указать значение PIPE_UNLIMITED_ INSTANCES, количество ка­налов будет определять ОС в зависимости от доступных системных ресурсов.

cbOutBuf и cbInBuf задают размеры в байтах буферов ввода и вывода, используе­мых для именованных каналов. Если указать нуль, будут использоваться значения по умолчанию.

dwTimeOut — принятый по умолчанию тайм-аут (в миллисекундах) для функции WaitNamedPipe. Эта ситуация, в которой функция создания определяет тайм-аут для другой функции, является уникальной.

Возвращаемое значение в случае ошибки — INVALID_HANDLE_VALUE, так как дескрипторы каналов подобны дескрипторам файлов.

lpsa играет ту же роль, что и в других функциях создания.

При первом вызове CreateNamedPipe фактически создается именованный канал, а не просто экземпляр. При закрытии последнего дескриптора экземпляра сам этот экземпляр удаляется. Удаление последнего экземпляра именованного канала вызывает удаление самого канала.

Подключение клиента к именованному каналу

Клиент может подключиться к именованному каналу с помощью вызова CreateFile с указанием имени канала. Во многих случаях клиент и сервер находятся на одной машине; тогда имя имеет вид: \\.\pipe\[путь]имя_канала

Если бы сервер находился на другой машине, имя выглядело бы так:

\\имя_сервера\pipe\[путь]имя_канала

Если сервер локальный, то применение для имени символа "." вместо указания имени самой машины значительно повышает быстродействие.

Функции состояния именованного канала

GetNamedPipeHandleState возвращает для данного открытого дескриптора сведения о том, находится ли канал в блокируемом или неблокируемом режиме, ориентирован ли он на сообщения или на байты, о количестве экземпляров канала и т.д.

SetNamedPipeHandleState позволяет программе задавать эти атрибуты состояния.

GetNamedPipelnfo определяет, связан ли дескриптор с клиентом или сервером, каков размер буфера и т.д.

Функции подключения именованного канала

После создания экземпляра именованного канала сервер может отслеживать под­ключение клиента (с помощью функций CreateFile или CallNamedPipe), используя функцию ConnectNamedPipe.

BOOL ConnectNamedPipe ( HANDLE hNamedPipe, LPOVERLAPPED lpo)

Если задать в lpo значение NULL, выполнение ConnectNamedPipe завершится сразу же, как только появится подключение клиента. Обычно функция возвращает TRUE. Значение FALSE может быть, если клиент подключается между вызовами сервером функций CreateNamedPipe и ConnectNamedPipe. В этом случае GetLastError воз­вращает значение ERROR_PIPE_CONNECTED.

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

Последняя функция, WaitNamedPipe, предназначена для синхронизации подключений клиента. Эта функция завершается, если на сервере имеется незавершенное обращение к ConnectNamedPipe. Используя WaitNamedPipe, клиент может убедить­ся, что сервер готов к подключению, после чего вызвать CreateFile. Кроме того, вы­зов сервером функции ConnectNamedPipe в этом случае завершится успешно.

Соединение клиента и сервера через именованный канал

Сначала в последовательности сервера осуществляется подключение клиента, с которым сервер связывается до тех пор, пока тот не разорвет соединение, затем сервер закрывает подключение на стороне сервера и соединяется с другим клиентом.

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

Обратите внимание, что между клиентом и сервером происходит состязание. Во-первых, вызов клиентом WaitNamedPipe завершится неудачно, если сервер еще не создал именованный канал. Во-вторых, возможны обстоятельства, в которых клиент может завершить свой вызов CreateFile прежде, чем сервер вызовет ConnectNamedPipe. В этом случае ConnectNamedPipe возвратит FALSE, но связь через именован­ный канал будет работать, как положено.

Транзакционные функции именованного канала

Клиент выполняет следующее:

• открывает экземпляр канала, создавая долговременное подключение к серверу и потребляя этот экземпляр канала;

  • попеременно посылает запросы и ожидает ответов;

  • закрывает подключение.

Обычную последовательность функций WriteFile, ReadFile можно считать отдельной транзакцией клиента, и в Win32 имеется такая функция для каналов сообщений.

BOOL TransactNamedPipe ( HANDLE hNamedPipe, LPVOID lpvWriteBuf,

DWORD cbWriteBuf, LPVOID lpvReadBuf, DWORD cbReadBuf,

LPDWORD lpcbRead, LPOVERLAPPED lpa)

Назначение параметров не нуждается в объяснении, так как эта функция пред­ставляет собой сочетание WriteFile и ReadFile для дескриптора именованного ка­нала. Указываются как выходной, так и входной буферы, а * lpcbRead задает длину сообщения.

Функция TransactNamedPipe удобна, но требует посто­янного подключения, что ограничивает число клиентов.

CallNamedPipe, вторая функция-полуфабрикат, лишена этого недостатка, так как объединяет в себе всю последовательность: CreateFile, WriteFile, ReadFile, CloseHandle.

Преимущество заключается в более эффективном использовании канала, несмотря на издержки подключения при каждом запросе.

BOOL CallNamedPipe ( LPCPSTR lpszPipeName, LPVOID lpvWriteBuf,

DWORD сbWriteBuf, LPVOID lpvReadBuf, DWORD сbReadBuf,

LPDWORD lpcbRead, DWORD dwTimeOut)

Использование параметров подобно TransactactNamedPipe с тем исключением, что для канала указывается имя, а не дескриптор. Функция CallNamedPipe является синхронной.

Здесь также указывается тайм-аут в миллисекундах — для подключения, но не для транзакции. Для dwTimeOut существует также три специальных значения:

  • NMPWAIT_NOWAIT;

  • NMPWAIT_WAIT_FOREVER;

  • NMPWAIT_USE_DEFAULT_WAIT — в этом случае используется тайм-аут по умолчанию, заданный при вызове CreateNamedPipe.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]