03Named Pipes.pptx
- Количество слайдов: 47
[Named] Pipes Каналы Pipe - средство передачи данных между параллельно работающими процессами. Они позволяют организовать передачу данных между локальными процессами, а также между процессами, запущенными на различных рабочих станциях в сети. Каналы типа Pipe больше всего похожи на файлы, поэтому они достаточно просты в использовании.
Через канал можно передавать данные только между двумя процессами. Один из процессов создает канал (сервер), другой открывает его (клиент). После этого оба процесса могут передавать данные через канал в одну или обе стороны, используя для этого функции, предназначенные для работы с файлами, такие как Read. File и Write. File. Приложения могут выполнять над каналами Pipe синхронные или асинхронные операции, аналогично тому, как это можно делать с файлами.
Именованные и анонимные каналы Существуют две разновидности каналов Pipe именованные (Named Pipes) и анонимные (Anonymous Pipes). Именованным каналам при создании присваивается имя, которое доступно для других процессов. Зная имя какой-либо рабочей станции в сети, процесс может получить доступ к каналу, созданному на этой рабочей станции. Анонимные каналы обычно используются для организации передачи данных между родительскими и дочерними процессами, запущенными на одной рабочей станции или на “отдельно стоящем” компьютере.
Имена каналов в общем случае имеют следующий вид: \Имя. СервераpipeИмя. Канала Если процесс открывает канал, созданный на другой рабочей станции, он должен указать имя сервера. Если же процесс создает канал или открывает канал на своей рабочей станции, вместо имени указывается символ точки: \. pipeИмя. Канала В любом случае процесс может создать канал только на той рабочей станции, где он запущен, поэтому при создании канала имя сервера никогда не указывается.
Реализации каналов В простейшем случае один серверный процесс создает один канал (точнее говоря, одну реализацию канала) для работы с одним клиентским процессом. Однако часто требуется организовать взаимодействие одного серверного процесса с несколькими клиентскими. Например, сервер базы данных может принимать от клиентов запросы и рассылать ответы на них. В случае такой необходимости серверный процесс может создать несколько реализаций канала, по одной реализации для каждого клиентского процесса.
Функции для работы с каналами Создание канала Для создания именованных и анонимных каналов Pipes используются функции Create. Pipe и Create. Named. Pipe. Функция Create. Pipe Анонимный канал создается функцией Create. Pipe, имеющей следующий прототип: BOOL Create. Pipe( PHANDLE h. Read. Pipe, // адрес переменной, в которую будет записан идентификатор канала для // чтения данных PHANDLE h. Write. Pipe, // адрес переменной, в которую будет записан идентификатор канала для // записи данных LPSECURITY_ATTRIBUTES lp. Pipe. Attributes, // адрес переменной для атрибутов защиты DWORD n. Size // количество байт памяти, зарезервированной для канала );
Канал может использоваться как для записи в него данных, так и для чтения. Поэтому при создании канала функция Create. Pipe возвращает два идентификатора, записывая их по адресу, заданному в параметрах h. Read. Pipe и h. Write. Pipe. h. Read. Pipe передаётся как параметр функциям Read. File или Read. File. Ex для выполнения операции чтения. h. Write. Pipe, передается функции Write. File или Write. File. Ex для выполнения операции записи. lp. Pipe. Attributes - адрес переменной, содержащей атрибуты защиты создаваемого канала. NULL означает что канал будет иметь атрибуты защиты, принятые по умолчанию. n. Size определяет размер буфера для создаваемого канала. 0 означает, что будет создан буфер размером, принятым по умолчанию. В случае успеха функция Create. Pipe возвращает значение TRUE, при ошибке - FALSE. Уточнить причину можно с помощью функции Get. Last. Error.
Функция Create. Named. Pipe Создаёт именованный канал. HANDLE Create. Named. Pipe( LPCTSTR lp. Name, // адрес строки имени канала DWORD dw. Open. Mode, // режим открытия канала DWORD dw. Pipe. Mode, // режим работы канала DWORD n. Max. Instances, // максимальное количество // реализаций канала DWORD n. Out. Buffer. Size, // размер выходного буфера в байтах DWORD n. In. Buffer. Size, // размер входного буфера в байтах DWORD n. Default. Time. Out, // время ожидания в миллисекундах LPSECURITY_ATTRIBUTES lp. Security. Attributes // адрес // переменной для атрибутов защиты );
Параметры: lp. Name - адрес строки имени канала в форме \. pipeИмя. Канала (имя сервера не указывается). dw. Open. Mode - режим, в котором открывается канал. - передача потока байт - константа PIPE_TYPE_BYTE (умолчание), - передача сообщений - PIPE_TYPE_MESSAGE Помимо способа передачи данных через канал, с помощью параметра dw. Open. Mode можно указать, будет ли данный канал использован только для чтения данных, только для записи или одновременно для чтения и записи. Способ использования канала задается указанием одной из следующих констант: PIPE_ACCESS_INBOUND - только для чтения PIPE_ACCESS_OUTBOUND - только для записи PIPE_ACCESS_DUPLEX - для чтения и записи
Перечисленные параметры должны быть одинаковы для всех реализаций (instances) канала. Существуют и такие, которые могут и отличаться для различных instances. (см MSDN ил конспект)
dw. Pipe. Mode - определяет режим работы канала. Параметр может включать перечисленные выше константы PIPE_TYPE_BYTE, PIPE_TYPE_MESSAGE, PIPE_READMODE_BYTE, PIPE_READMODE_MESSAGE, PIPE_WAIT и PIPE_NOWAIT. Для всех реализаций канала необходимо указывать один и тот же набор констант. n. Max. Instances определяет максимальное количество реализаций, которые могут быть созданы для канала. Значения от 1 до PIPE_UNLIMITED_INSTANCES. В последнем случае максимальное количество реализаций ограничивается только наличием свободных системных ресурсов. Если один серверный процесс использует несколько реализаций канала, то количество instances может быть меньше, чем потенциальное максимальное количество клиентов, т. к. клиенты могут использовать реализации по очереди.
n. Out. Buffer. Size и n. In. Buffer. Size – размеры входного и выходного буферов. n. Default. Time. Out определяет время ожидания для реализации канала. Должно быть одинаково для всех instances. lp. Pipe. Attributes - адрес переменной, содержащей атрибуты защиты для создаваемого канала. NULL – атрибуты по умолчанию. В случае успеха функция Create. Named. Pipe возвращает идентификатор созданной реализации канала, который можно использовать в операциях чтения и записи, выполняемых с помощью Read. File и Write. File.
Использование фукции Create. File Функция Create. File, предназначенная для работы с файлами, может также быть использована для создания новых каналов и открытия существующих. При этом вместо имени файла вы должны указать этой функции имя канала Pipe. (см. msdn http: //msdn. microsoft. com/enus/library/windows/desktop/aa 363858%28 v=vs. 8 5%29. aspx )
Пример использования Create. Named. Pipe : HANDLE h. Named. Pipe; LPSTR lpsz. Pipe. Name = "\\. \pipe\$My. Pipe$"; h. Named. Pipe = Create. Named. Pipe( lpsz. Pipe. Name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 512, 5000, NULL);
Установка соединения со стороны сервера После создания канала, сервер может выполнить соединение с клиентом. Соединение со стороны сервера выполняется с помощью функции Connect. Named. Pipe. BOOL Connect. Named. Pipe( HANDLE h. Named. Pipe, // идентификатор именованного канала LPOVERLAPPED lp. Overlapped // адрес структуры OVERLAPPED ); lp. Overlapped=NULL - только синхронные операции. Для канала, созданного в синхронном блокирующем режиме (PIPE_WAIT), функция Connect. Named. Pipe переводит канал в состояние ожидания соединения с клиентским процессом.
Если канал создан в синхронном неблокирующем режиме, функция Connect. Named. Pipe немедленно возвращает управление с кодом TRUE, если только клиент был отключен от данной реализации канала и возможно подключение клиента. В противном случае возвращается значение FALSE. Get. Last. Error может вернуть значение ERROR_PIPE_LISTENING (если к серверу еще не подключен ни один клиент), ERROR_PIPE_CONNECTED (если клиент уже подключен) ERROR_NO_DATA (если предыдущий клиент отключился от сервера, но новый клиент еще не завершил соединение).
Пример: HANDLE h. Named. Pipe; LPSTR lpsz. Pipe. Name = "\\. \pipe\$My. Pipe$"; h. Named. Pipe = Create. Named. Pipe( lpsz. Pipe. Name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 512, 5000, NULL); f. Connected = Connect. Named. Pipe(h. Named. Pipe, NULL); В данном случае функция Connect. Named. Pipe переведёт instance в состояние ожидания, так канал был создан для работы в синхронном блокирующем режиме.
Установка соединения со стороны клиента Для создания канала клиентский процесс может воспользоваться функцией Create. File. Эта функция предназначена для работы с файлами, однако с ее помощью можно также открыть канал, указав его имя вместо имени файла. Функция Create. File позволяет открывать не только файлы или каналы Pipe, но и другие системные ресурсы, например, устройства и каналы Mailslot.
HANDLE Create. File( LPCTSTR lp. File. Name, // строка, содержащая имя файла (канала) DWORD dw. Desired. Access, // режим доступа DWORD dw. Share. Mode, // режим совместного использования файла LPSECURITY_ATTRIBUTES lp. Security. Attributes, // дескриптор защиты DWORD dw. Creation. Disposition, // параметры создания DWORD dw. Flags. And. Attributes, // атрибуты файла HANDLE h. Template. File // идентификатор файла с атрибутами );
dw. Desired. Access определяет тип доступа к файлу (Pipe). 0 - доступ запрещен, однако приложение может определять атрибуты файла, канала или устройства, открываемого при помощи функции Create. File GENERIC_READ - Разрешен доступ на чтение из файла или канала Pipe GENERIC_WRITE - разрешен доступ на запись в файл или канал Pipe Тип доступа, указанный при помощи параметра dw. Desired. Access, не должен противоречить типу доступа для канала, заданного при его создании функцией Create. Named. Pipe.
dw. Share. Mode задаёт режим совместного использования открываемого или создаваемого файла. Для этого параметра вы можете указать комбинацию следующих констант: 0 - совместное использование файла запрещено FILE_SHARE_READ - другие приложения могут открывать файл с помощью функции Create. File для чтения FILE_SHARE_WRITE аналогично предыдущему, но на запись
lp. Security. Attributes - указатель на дескриптор защиты или NULL, если этот дескриптор не используется. В наших приложениях мы не работаем с дескриптором защиты. dw. Creation. Disposition определяет действия, выполняемые функцией Create. File, если приложение пытается создать файл, который уже существует.
dw. Creation. Disposition принимает значения:
Параметр dw. Flags. And. Attributes задает атрибуты и флаги для файла. Можно использовать любые логические комбинации следующих атрибутов (кроме атрибута FILE_ATTRIBUTE_NORMAL, который можно использовать только отдельно): h. Template. File – не будем рассматривать (NULL)
Фрагмент исходного текста клиентского приложения, открывающего канал с именем $My. Pipe$ при помощи функции Create. File: char sz. Pipe. Name[256]; HANDLE h. Named. Pipe; strcpy(sz. Pipe. Name, "\\. \pipe\$My. Pipe$"); h. Named. Pipe = Create. File( sz. Pipe. Name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); Здесь канал открывается как для записи, так и для чтения.
Функция Read. File Читает данные из указанного файла или периферийного устройства. Чтение выполняется от текущей позиции в файле ( если понятие позиции поддерживается файлом или устройством). Функция предназначена как для синхронных, так и асинхронных операций. Аналогичная функция Read. File. Ex предназначена исключительно для асинхронных операций. BOOL WINAPI Read. File( HANDLE h. File, // дескриптор канала LPVOID lp. Buffer, // буфер в который происходит чтение DWORD n. Number. Of. Bytes. To. Read, // сколько байт прочитать LPDWORD lp. Number. Of. Bytes. Read, // сколькл байт прочитано LPOVERLAPPED lp. Overlapped // игнорируем (NULL) );
Параметры: • h. File [in] – дескриптор файла, устройства или именованного канала. Для асинхронных операций, h. File может быть любым дескриптором, открытым с флагом FILE_FLAG_OVERLAPPED flag функцией Create. File. • lp. Buffer [out] – указатель на буфер для чтения. • n. Number. Of. Bytes. To. Read [in] – сколько байт следует читать. • lp. Number. Of. Bytes. Read [out, optional] – указатель на переменную в которую буде помещено число действительно прочитанных байт (для синхронных операций). Для асинхронных следует указывать NULL. • lp. Overlapped [in, out, optional] –указатель на структуру OVERLAPPED. Требуется если h. File был открыт с флагом FILE_FLAG_OVERLAPPED, в противном случае может быть NULL. Возвращает true в случае успеха.
Пример HANDLE h. Named. Pipe; DWORD cb. Written; char sz. Buf[256]; Write. File(h. Named. Pipe, sz. Buf, strlen(sz. Buf) + 1, &cb. Written, NULL);
Функция Write. File Пишет данные в файл или устройство. Используется как для синхронных, так и асинхронных операций. Write. File. Ex – исключительно для асинхронных. BOOL WINAPI Write. File( HANDLE h. File, // дескриптор файла (канала) LPCVOID lp. Buffer, // буфер, содержимое которого пишется в канал DWORD n. Number. Of. Bytes. To. Write, // число байт которые надо записать LPDWORD lp. Number. Of. Bytes. Written, // число действительно записанных байт LPOVERLAPPED lp. Overlapped // структура OVERLAPPED (см. ниже или не стоит? ) ); В случае успеха возвращает true.
Отключение сервера от клиента Если сервер работает с несколькими клиентскими процессами, то он может использовать для этого несколько реализаций канала, причем одни и те же реализации могут применяться по очереди. Установив канал с клиентом при помощи функции Connect. Named. Pipe, сервер может затем разорвать канал, вызвав для этого функцию Disconnect. Named. Pipe. После этого реализация канала может быть вновь использована для соединения с другим или тем же клиентским процессом. Прототип функции Disconnect. Named. Pipe: BOOL Disconnect. Named. Pipe(HANDLE h. Named. Pipe); Через параметр h. Named. Pipe функции передается идентификатор реализации канала Pipe, полученный от функции Create. Named. Pipe. В случае успеха функция возвращает значение TRUE, а при ошибке - FALSE
Закрытие идентификатора канала Если канал больше не нужен, после отключения от клиентского процесса серверный и клиентский процессы должны закрыть его идентификатор функцией Close. Handle: Close. Handle(h. Named. Pipe);
Функция Call. Named. Pipe Обычно сценарий взаимодействия клиентского процесса с серверным заключается в выполнении следующих операций: 1. подключение к каналу с помощью функции Create. File; 2. выполнение операций чтения или записи такими функциями как Read. File или Write. File; 3. отключение от канала функцией Close. Handle. Функция Call. Named. Pipe позволяет выполнить эти операции за один прием, при условии что канал открыт в режиме передачи сообщений и что клиент посылает одно сообщение серверу и в ответ также получает от сервера одно сообщение.
Прототип функции Call. Named. Pipe: BOOL Call. Named. Pipe( LPCTSTR lp. Named. Pipe. Name, // адрес имени канала LPVOID lp. Out. Buffer, // адрес буфера для записи DWORD n. Out. Buffer. Size, /* размер буфера для записи */ LPVOID lp. In. Buffer, // адрес буфера для чтения DWORD n. In. Buffer. Size, /* размер буфера для чтения */ LPDWORD lp. Bytes. Read, /* адрес переменной для записи количества прочитанных байт данных */ DWORD n. Time. Out); /* время ожидания в миллисекундах */
n. Time. Out определяет, в течении какого времени функция Call. Named. Pipe будет ожидать доступности канала Pipe, прежде чем она вернет код ошибки. Помимо численного значения в миллисекундах, может быть указана одна из следующих констант: • NMPWAIT_NOWAIT - ожидание канала Pipe не выполняется. Если канал не доступен, функция Call. Named. Pipe сразу возвращает код ошибки • NMPWAIT_FOREVER - ожидание выполняется бесконечно долго • NMPWAIT_USE_DEFAULT_WAIT - Ожидание выполняется в течении периода времени, указанного при вызове функции Create. Named. Pipe В случае успешного завершения функция Call. Named. Pipe возвращает значение TRUE.
Функция Transact. Named. Pipe, также как и функция Call. Named. Pipe, предназначена для выполнения передачи и приема данных от клиентского процесса серверному. Однако эта функция более гибкая в использовании, чем функция Call. Named. Pipe. Перед использованием функции Transact. Named. Pipe клиентский процесс должен открыть канал с сервером, воспользовавашись для этого, например, функцией Create. File. Клиентский процесс может выполнять обмен данными с сервером, вызывая функцию Transact. Named. Pipe много раз. При этом не будет происходить многократного открытия и закрытия канала.
Прототип Transact. Named. Pipe BOOL Transact. Named. Pipe( HANDLE h. Named. Pipe, /* идентификатор канала Pipe */ LPVOID lpv. Write. Buf, // адрес буфера для записи DWORD cb. Write. Buf, // размер буфера для записи LPVOID lpv. Read. Buf, // адрес буфера для чтения DWORD cb. Read. Buf, // размер буфера для чтения LPDWORD lpcb. Read, /* адрес переменной, в которую будет записано количество действительно прочитанных байт */ LPOVERLAPPED lpov); /* адрес структуры типа OVERLAPPED */
Функция Peek. Named. Pipe Чтение данных из канала функцией Read. File вызывает удаление прочитанных данных. Функция Peek. Named. Pipe позволяет получить данные из именованного или анонимного канала без удаления, так что при последующих вызовах этой функции или функции Read. File будут получены все те же данные, что и при первом вызове функции Peek. Named. Pipe. Функция Peek. Named. Pipe никогда не переходит в состояние ожидания, сразу возвращая управление вне зависимости от того, есть данные в канале или нет.
Прототип Peek. Named. Pipe BOOL Peek. Named. Pipe( HANDLE h. Pipe, // идентификатор канала Pipe LPVOID lpv. Buffer, // адрес буфера для прочитанных данных DWORD cb. Buffer, // размер буфера прочитанных данных LPDWORD lpcb. Read, // адрес переменной, в которую будет // записано количество действительно // прочитанных байт данных LPDWORD lpcb. Avail, // адрес переменной, в которую будет записано общее количество байт данных, доступных в канале для чтения */ LPDWORD lpcb. Message); /* адрес переменной, в которую будет записано количество непрочитанных байт в данном сообщении */
Функция Wait. Named. Pipe С помощью функции Wait. Named. Pipe процесс может задать время ожидания момента, когда канал Pipe будет доступен для соединения: BOOL Wait. Named. Pipe( LPCTSTR lpsz. Pipe. Name, // адрес имени канала Pipe DWORD dw. Timeout); // время ожидания в миллисекундах Помимо численного значения в миллисекундах, можно указать одну из констант: NMPWAIT_FOREVER - ожидание выполняется бесконечно долго NMPWAIT_USE_DEFAULT_WAIT - ожидание выполняется в течении периода времени, указанного при вызове функции Create. Named. Pipe Если канал стал доступен до истечения периода времени, заданного параметром dw. Timeout, функция Wait. Named. Pipe возвращает значение TRUE.
Функция Set. Named. Pipe. Handle. State Изменяет режимы работы для уже созданного канала Pipe. BOOL Set. Named. Pipe. Handle. State( HANDLE h. Named. Pipe, // идентификатор канала Pipe LPDWORD lpdw. Mode, /* адрес переменной, в которой указан новый режим канала */ LPDWORD lpcb. Max. Collect, /* адрес переменной, в которой указывается максимальный размер пакета, передаваемого в канал */ LPDWORD lpdw. Collect. Data. Timeout); /* адрес максимальной задержки передачей данных */
Новый режим работы записывается в переменную, адрес которой задан через параметр lpdw. Mode. Может быть указана одна из констант: PIPE_READMODE_BYTE - канал открывается на чтение в режиме последовательной передачи отдельных байт PIPE_READMODE_MESSAGE - канал открывается на чтение в режиме передачи отдельных сообщений указанной длины PIPE_WAIT - канал будет работать в блокирующем режиме, когда процесс переводится в состояние ожидания до завершения операций в канале PIPE_NOWAIT - неблокирующий режим работы канала. Если операция не может быть выполнена немедленно, в неблокирующем режиме функция завершается с ошибкой Константы PIPE_WAIT и PIPE_NOWAIT, задающие блокирующий и неблокирующий режим соответственно, можно комбинировать при помощи логической операции ИЛИ с константами PIPE_READMODE_BYTE и PIPE_READMODE_MESSAGE. Если текущий режим работы канала изменять не нужно, для параметра lpdw. Mode следует указать значение NULL.
lpcb. Max. Collect. Если при открытии канала клиентским процессом функцией Create. File не была указана константа FILE_FLAG_WRITE_THROUGH, то данные передаются пакетами, которые собираются из отдельных сообщений. Размер такого пакета определяет параметр lpcb. Max. Collect. Если размер пакета не должен изменяться, то lpcb. Max. Collect д. быть NULL.
lpdw. Collect. Data. Timeout задает максимальный интервал между передачами данных по сети. Если функция Set. Named. Pipe. Handle. State изменяет параметры канала со стороны сервера, или если сервер и клиент работают на одном и том же компьютере, параметр lpdw. Collect. Data. Timeout должен быть задан как NULL.
Функция Get. Named. Pipe. Handle. State - определяет состояние канала Pipe Прототип функции Get. Named. Pipe. Handle. State: BOOL Get. Named. Pipe. Handle. State( HANDLE h. Named. Pipe, // идентификатор именованного канала LPDWORD lp. State, // адрес флагов состояния канала LPDWORD lp. Cur. Instances, // адрес количества реализаций канала LPDWORD lp. Max. Collection. Count, // адрес размера пакета // передаваемых данных LPDWORD lp. Collect. Data. Timeout, // адрес максимального // времени ожидания LPTSTR lp. User. Name, // адрес имени пользователя // клиентского процесса DWORD n. Max. User. Name. Size); // размер буфера для // имени пользователя клиентского процесса
lp. State - указатель на переменную типа DWORD, в которую будет записан один из флагов состояния канала: • PIPE_WAIT - Канал будет работать в блокирующем режиме, когда процесс переводится в состояние ожидания до завершения операций в канале • PIPE_NOWAIT - неблокирующий режим работы канала. Если операция не может быть выполнена немедленно, в неблокирующем режиме функция завершается с ошибкой Если информация о состоянии канала не требуется, to lp. State=NULL.
Функция Get. Named. Pipe. Info тоже позволяет получить информацию об именованном канале по его идентификатору BOOL Get. Named. Pipe. Info( HANDLE h. Named. Pipe, // идентификатор канала LPDWORD lp. Flags, // адрес флагов типа канала LPDWORD lp. Out. Buffer. Size, /* адрес размера выходного буфера */ LPDWORD lp. In. Buffer. Size, /* адрес размера входного буфера */ LPDWORD lp. Max. Instances); /* адрес максимального количества реализаций канала */
В lp. Flags помещаются флаги канала. Если не требуется – NULL. Ниже приведены возможные значения флагов: • PIPE_CLIENT_END - идентификатор ссылается на клиентскую часть канала • PIPE_SERVER_END - идентификатор ссылается на серверную часть канала • PIPE_TYPE_MESSAGE - канал работает в режиме передачи сообщений lp. Out. Buffer. Size и lp. In. Buffer. Size – размеры выходного и входного буферов lp. Max. Instances - максимальное значение реализаций, которое можно создать для данного канала. Если будет получено PIPE_UNLIMITED_INSTANCES, количество реализаций ограничивается только свободными системными ресурсами.