Функции для работы с каналами — КиберПедия 

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Функции для работы с каналами

2019-09-17 193
Функции для работы с каналами 0.00 из 5.00 0 оценок
Заказать работу

    В табл. 1 представлен список основных функций для работы с именованными каналами.

 Таблица 1

Функции для работы с каналами

Функции Краткое описание функций
CreateNamedPipe Создание именованного канала или нового экземпляра канала. Функция доступна только серверу.
ConnectNamedPipe            или CreateFile Подключение к экземпляру именованного канала со стороны клиента. Функция доступна только клиенту.
WaitNamedPipe Ожидание клиентом появления свободного экземпляра именованного канала для подключения к нему.
ConnectNamedPipe Ожидание сервером подключения клиента к экземпляру именованного канала.
ReadFile, ReadFileEx Чтение данных из именованного канала. Функция доступна как клиенту, так и серверу.
WriteFile, WriteFileEx Запись данных в именованный канал. Функция доступна как клиенту, так и серверу.
PeekNamedPipe Чтение данных из именованного канала без удаления прочитанных данных из буфера канала. Функция доступна как клиенту, так и серверу.

 

Продолжение табл. 1

TransactNamedPipe Запись и чтение из именованного канала одной операцией. Функция доступна как клиенту, так и серверу.
DisconnectNamedPipe Отсоединение сервера от экземпляра именованного канала.
GetNamedPipeInfo Получение информации об именованном канале.
GetNamedPipeHandleState Получение текущего режима работы именованного канала и количества созданных экземпляров канала.
SetNamedPipeHandleState Установка текущего режима работы именованного канала.
CloseHandle Закрытие дескриптора экземпляра именованного канала, освобождение связанных с объектом ресурсов.
FlushFileBuffers Сброс данных из кэша в буфер канала.

 

Функция CallNamedPipe

Обычно сценарий взаимодействия клиентского процесса с серверным заключается в выполнении следующих операций:

- подключение к каналу с помощью функции CreateFile;

- выполнение операций чтения или записи такими функциями как ReadFile или WriteFile;

- отключение от канала функцией CloseHandle.

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

BOOL CallNamedPipe(

LPCTSTR IpNamedPipeName, // адрес имени канала

LPVOID lpOutBuffer, // адрес буфера для записи

DWORD nOutBufferSize, // размер буфера для записи

LPVOID lpInBuffer, // адрес буфера для чтения

DWORD nlnBufferSize, // размер буфера для чтения

LPDWORD IpBytesRead, // адрес переменной для записи // количества прочитанных байт данных

DWORD nTimeOut); // время ожидания в миллисекундах

Перед вызовом функции CallNamedPipe необходимо записать в параметр IpNamedPipeName указатель на текстовую строку, содержащую имя канала Pipe. Адрес и размер буфера содержащий передаваемые через канал данные следует указать функции CallNamedPipe соответственно через параметры lpOutBuffer и nOutBufferSize.

Данные, полученные от сервера в ответ на посланное ему сообщение, будут записаны в буфер. Адрес этого буфера необходимо указать через параметр lpInBuffer, a размер буфера - через параметр nlnBufferSize.

В переменную, адрес которой указан через параметр IpBytesRead, записывается количество байт, полученных через канал от сервера.

Параметр nTimeOut определяет, в течении какого времени функция CallNamedPipe будет ожидать доступности канала Pipe, прежде чем она вернет код ошибки.

Функция CreateNamedPipe.

HANDLE CreateNamedPipe(

LPCTSTR lpName,    // адрес строки имени канала

DWORD dwOpenMode, // режим открытия канала

DWORD dwPipeMode, // режим работы канала

DWORD nMaxInstances, // максимальное количество // реализаций канала

DWORD nOutBufferSize, // размер выходного буфера в байтах

DWORD nlnBufferSize, // размер входного буфера в байтах

DWORD nDefaultTimeOut, // время ожидания в миллисекундах

LPSECURITY ATTRIBUTES lpSecurity Attributes); // адрес

// переменной для атрибутов защиты

Через параметр lpName передается адрес строки имени канала в форме \\.\рiре\ИмяКанала (напомним, что при создании канала имя сервера не указывается, так как канал можно создать только на той рабочей станции, где запущен процесс, создающий канал).

Параметр dwOpenMode задает режим, в котором открывается канал. Режим работы канала (ориентированный на передачу байт или сообщений) задается соответственно константами PIPE_TYPE_BYTE или PIPE_TYPE_MESSAGE,. По умолчанию используется режим PIPE_TYPE_BYTE.

Помимо способа передачи данных через канал с помощью параметра dwOpenMode можно указать, будет ли данный канал использован только для чтения данных, только для записи или одновременно для чтения и записи. Способ использования канала задается указанием одной из следующих констант:

             Константа                                  Использование канала

PIPE_ACCESS_INBOLJND                         Только для чтения

PIPE_ACCESS_OUTBOND                         Только для записи      

PIPE_ACCESS_DUPLEX                             Для чтения и записи

Перечисленные выше параметры должны быть одинаковы для всех экземпляров канала.

Далее перечисляются параметры, которые могут отличаться для разных реализаций канала:

             Константа                                    Использование канала

PIPE_READ_MODE_BYTE     Канал открывается на чтение в режиме последовательной передачи отдельных байт

PIPE_ READ_ MODE_MESSAGE  Канал открывается на чтение в режиме передачи отдельных сообщений указанной длины

PIPE_WAIT                             Канал будет работать в блоки-рующем режиме, когда процесс переводится в состояние ожидания до завершения операций в канале

PIPE_NO_WAIT                                Неблокирующий режим работы канала. Если операция не может быть выполнена немедленно, в неблокирующем режиме функция завершается с ошибкой

 FILE_FLAG_OVERLAPPED Использование асинхронных операций (ввод и вывод с перекрытием). Данный режим позволяет процессу выполнять полезную работу параллельно с проведением операций в канале

FILE_FLAG_WRITE_THROUGH В этом режиме функции, работающие с каналом, не возвращают.управление до тех пор, пока не будет полностью завершена операция на удаленном компьютере. Используется только с каналом, ориентированном на передачу отдельных байт и только b том случае, когда канал создан между процессами, запущенными на различных станциях сети

Дополнительно к перечисленным выше флагам через параметр dwOpenMode можно передавать следующие флаги защиты:

             Флаг                                                 Описание                                                                                       

WRITE_DAC                              Вызывающий процесс должен иметь права доступа на запись к произвольному управляю-щему списку доступа именованного канала access control list (ACL)

WRITE_OWNER                        Вызывающий процесс должен иметь права доступа на запись к процессу, владеющему именованным каналом Pipe

ACCESS_SYSTEM_SECURITY   Вызывающий процесс должен иметь права доступа на запись к управляющему списку доступа именованного канала access control list (ACL)

Параметр dwPipeMode определяет режим работы канала. В этом параметре можно указать перечисленные выше константы PIPE_TYPE_BYTE, PIPE_TYPE_MESSAGE, PIPE_ READ_MODE_BYTE, P1PE_READ_MODE_MESSAGE, P1PE_WA1T и PIPE_NOWA1T. Для всех экземпляров канала необходимо указывать один и тот же набор констант.

Параметр nMaxInstances определяет максимальное количество экземпляров, которые могут быть созданы для канала. Можно указывать здесь значения от 1 до PIPE_UNLIMITED_INSTANCES. В последнем случае максимальное количество реализаций ограничивается только наличием свободных системных ресурсов. Заметим, что если один серверный процесс использует несколько реализаций канала для связи с несколькими клиентскими, то общее количество реализаций может быть меньше, чем потенциальное максимальное количество клиентов. Это связано с тем, что клиенты могут использовать реализации по очереди, если только они не пожелают связаться с серверным процессом все одновременно.

Параметры nOutBufferSize и nlnBufferSize определяют соответственно размер буферов, используемых для записи в канал и чтения из канала. При необходимости система может использовать буферы других, по сравнению с указанными, размеров.

Параметр nDefaultTimeOut определяет время ожидания для реализации канала. Для всех реализаций необходимо указывать одинаковое значение этого параметра.

Через параметр lpPipeAttributes передается адрес переменной, содержащей атрибуты защиты для создаваемого канала. Обычно указывают этот параметр как NULL. В результате канал будет иметь атрибуты защиты, принятые по умолчанию.

В случае успеха функция CreateNamedPipe возвращает описатель (дескриптор) созданной реализации канала, который можно использовать в операциях чтения и записи, выполняемых с помощью таких функций, как ReadFile и WriteFile.

При ошибке функция CreateNamedPipe возвращает значение INVALID_HANDLE_VALUE. Код ошибки можно уточнить, вызвав функцию GetLastError.

Функция ConnectNamedPipe

BOOL ConnectNamedPipe(

HANDLE hNamedPipe, // описатель именованного канала

LPOVERLAPPED lpOverlapped); // адрес структуры OVERLAPPED

Через первый параметр серверный процесс передает этой функции описатель канала, полученный от функции CreateNamedPipe.

Второй параметр используется только для организации асинхронного обмена данными через канал. Если используются только синхронные операции, в качестве значения для этого параметра можно указать NULL. В случае успеха функция ConnectNamedPipe возвращает значение TRUE, а при ошибке - FALSE. Код ошибки можно получить с помощью функции GelLastError.

В зависимости от различных условий функция ConnectNamedPipe может вести себя по-разному. Если параметр lpOverlapped указан как NULL, функция выполняется в синхронном режиме. В противном случае используется асинхронный режим.

Для канала, созданного в синхронном блокирующем режиме (с использованием константы P1PE_WAIT), функция ConnectNamedPipe переходит в состояние ожидания соединения с клиентским процессом. Если канал создан в синхронном неблокирующем режиме, функция ConnectNamedPipe немедленно возвращает управление с кодом TRUE, если только клиент был отключен от данной реализации канала и возможно подключение этого клиента. В противном случае возвращается значение FALSE. Дальнейший анализ необходимо выполнять с помощью функции GetLastError. Эта функция может вернуть значение ERROR_PIPE_LISTENING (если к серверу еще не подключен ни один клиент), ERROR__PIPE__CONNECTED (если клиент уже подключен) или ERROR_NO_DATA (если предыдущий клиент отключился от сервера, но клиент еще не завершил соединение.

Функция DisconnectNamedPipe

BOOL DisconnectNamedPipe(HANDLE hNamedPipe);

Через параметр hNamedPipe функции передается идентификатор реализации канала Pipe, полученный от функции CreateNamedPipe.

В случае успеха функция возвращает значение TRUE, а при ошибке - FALSE. Код ошибки можно получить от функции GetLastError.

Функция WaitNamedPipe

BOOL WaitNamedPipe(

LPCTSTR IpNamedPipeName, // адрес имени канала

DWORD nTimeOut); // время ожидания в миллисекундах

    Параметр IpNamedPipeName определяет имя канала. Второй параметр определяет время ожидания свободного экземпляра канала.

Функция CreateFile

HANDLE CreateFile(

LPCTSTR ipFileName, // адрес строки имени файла

WORD dwDesiredAccess, // режим доступа

DWORD dwShareMode, // режим совместного использования файла

LPSECURITYATTRIBUTES lpSecurityAttributes, // дескриптор защиты

DWORD dwCreationDistribution, // параметры создания

DWORD dwFlagsAndAttributes, // атрибуты файла

HANDLE hTemplateFile); // идентификатор файла с атрибутами

При работе с файлами через параметр lpFileName передаётся адрес строки, содержащей имя файла, который создаётся или открывается. Строка должна быть закрыта двоичным нулем. Если функция CreateFile работает с каналом Pipe, параметр lpFileName определяет имя канала.

Параметр dwDesiredAccess определяет тип доступа, который должен быть предоставлен к открываемому файлу. В нашем случае этот тип доступа будет относиться к каналу Pipe.

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

С помощью параметра dwShareMode задаются режимы совместного использования открываемого или создаваемого файла. Для этого параметра используется комбинация следующих констант

    Константа                                                  Описание                                                                                                                

 О                                  Совместное использование файла запрещено

FILESHAREJREAD         Другие приложения могут открывать файл с помощью функции CreateFile для чтения

FILE_SHARE_WRITE        Аналогично предыдущему, но на запись

Через параметр lpSecurityAttributes необходимо передать указатель на дескриптор защиты или значение NULL, если этот дескриптор не используется.

Параметр dwCreationDistribution определяет действия, выполняемые функцией CreateFile, если приложение пытается создать файл, который уже существует. Для этого параметра указывается одна из следующих констант:

           Константа                                          Описание

CREAT_ENEW                  Если создаваемый файл уже существует, функция CreateFile возвращает код ошибки

CREATE_ALWAYS         Существующий файл перезаписывается, при этом содержимое старого файла теряется

OPEN_EXISTING              Открывается существующий файл. Если файл с указанным именем не существует, функция CreateFile возвращает код ошибки

OPEN_ALWAYS                Если указанный файл существует, он открывается. Если файл не существует, он будет создан

TRUNCATE_EXISTING  Если файл существует, он открывается, после чего длина файла устанавливается равной нулю. Содержимое старого файла теряется. Если же файл не существует, функция CreateFile возвращает код ошибки.      

Параметр dwFlagsAndAttributes задает атрибуты и флаги для файла.При этом можно использовать любые логические комбинации следующих атрибутов (кроме атрибута FILE_ATTRIBUTE_NORMAL, который можно использовать только отдельно):

               Атрибут                                          Описание

FILE_ATTRIBUTE_ARCHIVE         Файл был архивирован (выгру-жен)

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

FILE_ATTRIBUTE_NORMAL      Остальные перечисленные в этом списке атрибуты не установлены

FTLEJ_aTTRIBUTE_HIDDEN              Файл можно только читать

FILE _ATTRIBUTE_ SYSTEM      Файл является частью опера-ционной системы

В дополнение к перечисленным выше атрибутам, через параметр dwFlagsAndAttributes можно передать любую логическую комбинацию флагов, перечисленных ниже:

                 Флаг                                              Описание               

FILE_FLAG_WRITE_THROUGH  Отмена промежуточного кэширования данных для уменьшения вероятности потери данных при аварии

FILE_FLAG_NO_BUFFERING                        Отмена промежу-точной буферизации или кэширования. При исполь-зовании этого флага необхо-димо выполнять чтение и запись порциями, кратными размеру сектора (512 байт).

FILE_FLAG_OVERLAPPED              Асинхронное выполнение чте-ния и записи. Во время асинхронного чтения или записи приложение может продолжать обработку данных

FILE_FLAG_RANDOM_ACCESS     Указывает, что к файлу будет выполняться произвольный доступ. Флаг предназначен для оптимизации кэши-рования

 FILE_FLAG_SEQUENTIAL_SCAN Указывает, что к файлу будет выполняться последователь-ный доступ от начала файла к его концу. Флаг предназна-чен для оптимизации кэширования                      

FILE_FLAG_DELETE_ON_CLOSE Файл будет удален сразу после того, как приложение закроет его идентификатор. Этот флаг удобно использовать для временных файлов

FILE_FLAG_BACKUP_SEMANTICS Файл будет использован для выполнения операции вы-грузки или восстановления. При этом выполняется проверка прав доступа

FILE_FLAG_POSIX_SEMANTICS Доступ к файлу будет выполняться в соответствии со спецификацией POSIX                                                          

И, наконец, последний параметр hTemplateFile предназначен для доступа к файлу шаблона с расширенными атрибутами создаваемого файла.

В случае успешного завершения функция CreateFile возвращает описатель созданного или открытого файла (или каталога), а при работе с каналом Pipe – описатель экземпляра канала.

При ошибке возвращается значение INVALID_HANDLE_VALUE (а не NULL, как можно было бы предположить). Код ошибки можно определить при помощи функции GetLastError.

В том случае, если файл уже существует и были указаны константы CREATE_ALWAYS или OPEN_ALWAYS, функция CreateFile не возвращает код ошибки. В то же время в этой ситуации функция GetLastError возвращает значение ERROR_ALREADY_EXISTS.

Чтение данных из канала

Для чтения данных из канала можно воспользоваться функцией ReadFile, например, так:

HANDLE hNamedPipe;

DWORD cbRead;

char szBuf[256];

ReadFile(hNamedPipe, szBuf, 512, &cbRead, NULL);

Данные, прочитанные из канала hNamedPipe, будут записаны в буфер szBuf, имеющий размер 512 байт. Количество действительно прочитанных байт данных будет сохранено функцией ReadFile в переменной cbRead. Так как последний параметр функции указан как NULL, используется синхронный режим работы без перекрытия.

Функция CallNamedPipe

Обычно сценарий взаимодействия клиентского процесса с серверным заключается в выполнении следующих операций:

-  подключение к каналу с помощью функции CreateFile;

- выполнение операций чтения или записи такими функциями, как ReadFile или WriteFile;

-  отключение от канала функцией CloseHandle.

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

BOOL CallNamedPipe(

LPCTSTR IpNamedPipeName, // адрес имени канала

LPVOID lpOutBuffer,            // адрес буфера для записи

DWORD nOutBufferSize,  // размер буфера для записи

LPVOID lpInBuffer,            // адрес буфера для чтения

DWORD nlnBufferSize,      // размер буфера для чтения

LPDWORD IpBytesRead   // адрес переменной для записи // количества прочитанных байт данных

DWORD nTimeOut); // время ожидания в миллисекундах

Перед вызовом функции CallNamedPipe необходимо записать в параметр IpNamedPipeName указатель на текстовую строку, содержащую имя канала Pipe. Адрес и размер буфера содержащий передаваемые через канал данные следует указать функции CallNamedPipe соответственно через параметры lpOutBuffer и nOutBufferSize.

Данные, полученные от сервера в ответ на посланное ему сообщение, будут записаны в буфер. Адрес этого буфера необходимо указать через параметр lpInBuffer, a размер буфера - через параметр nlnBufferSize.

В переменную, адрес которой указан через параметр IpBytesRead, записывается количество байт, полученных через канал от сервера.

Параметр nTimeOut определяет, в течение какого времени функция CallNamedPipe будет ожидать доступности канала Pipe, прежде чем она вернет код ошибки.

Функция GetNamedPipeHandleState

С помощью функции GetNamedPipeHandleState процесс может определить состояние канала Pipe, зная его идентификатор.

BOOL GetNamedPipeHandleState(

HANDLE hNamedPipe, // идентификатор именованного канала

LPDWORD lpState,  // адрес флагов состояния канала

LPDWORD ipCurlnstances,    // адрес количества реализаций

LPDWORD lpMaxCollectionCount, // адрес размера пакета передаваемых данных

LPDWORD ipCollectDataTimeout, // адрес максимального времени ожидания

LPTSTR lpUserName, // адрес имени пользователя клиентского процесса

DWORD nMaxUserNameSize); // размер буфера для имени пользователя клиентского процесса

Идентификатор канала, для которого нужно определить состояние, передается функции GetNamedPipeHandleState через параметр hNamedPipe.

Через параметр lpState нужно передать указатель на переменную типа DWORD, в которую будет записан один из флагов состояния канала:

          Флаги состояния                          | Описание

PIPE_WAIT                  Канал будет работать в блокирующем режиме, когда процесс переводится в состояние ожидания до завершения операций в канале    

PIPE_NOWAIT                     Неблокирующий режим работы канала. Если операция не может быть выполнена немедленно, в неблокирующем режиме функция завершается с ошибкой

Если информация о состоянии канала не требуется, в качестве значения для параметра lpState следует использовать константу NULL.

В переменную, адрес которой передается через параметр IpCurlnstances, записывается текущее количество реализаций канала. Если эта информация не нужна, передаётся через параметр ipCurTnstances значение NULL.

Параметры lpMaxCollectionCount и IpCollectDataTimeout позволяют определить соответственно размер пакета передаваемых данных и максимальное время ожидания между передачами.

Через параметр lpUserName передаётся указатель на буфер, в который функция GetNamedPipeHandleState запишет имя пользователя клиентского процесса. Размер этого буфера задается в параметре nMaxUserNameSize.

При необходимости задаётся значения параметров lpMaxCollectionCount, IpCollectDataTimeout и lpUserName как NULL. В этом случае соответствующая информация не будет извлекаться.

В случае успешного завершения функция GetNamedPipeHandleState возвращает значение TRUE, а при ошибке - FALSE.

Функция GetNamedPipelnfo

Еще одна функция, позволяющая получить информацию об именованном канале по его идентификатору.

BOOL GetNamedPipeInfo(

HANDLE hNamedPipe, // идентификатор канала

LPDWORD IpFlags,    // адрес флагов типа канала

LPDWORD lpOutBufferSize, // адрес размера выходного буфера

LPDWORD lpInBufferSize, // адрес размера входного буфера

LPDWORD lpMaxInstances); // адрес максимального количества реализаций канала

Параметр hNamedPipe задает идентификатор именованного канала Pipe, для которого требуется получить информацию.

Через параметр IpFlags функции GetNamedPipeTnfo необходимо передать адрес переменной типа DWORD или NULL, если флаги определять не требуется. Ниже приведены возможные значения флагов:

Флаг                                                            Описание

PIPE_CLIENT_END          Идентификатор ссылается на кли-ентскую часть канала

PIPE_SERVER_END          Идентификатор ссылается на сер-верную часть канала

PIPE _TYPE_ MESSAGE            Канал работает в режиме передачи сообщений                                      

В переменные, адреса которых задаются через параметры lpOutBufferSize и lpInBufferSize, функция GetNamedPipelnfo заносит размеры входного и выходного буфера соответственно. Если эта информация не нужна, передаётся через параметры lpOutBufferSize и lpInBufferSize значение NULL. И, наконец, через параметр lpMaxInstances передается адрес переменной, в которую будет записано максимальное значение реализаций, которое можно создать для данного канала. Если после вызова функции GetNamedPipelnfo в этой переменной записано значение PIPE_UNLIMITED_INSTANCES, количество реализаций ограничивается только свободными системными ресурсами.

В случае успешного завершения функция GetNamedPipelnfo возвращает значение TRUE, а при ошибке - FALSE.

Примеры программ простого сервера и клиента представлены в приложении. Также представлена программа реализации усовершенствованного сервера с использованием перекрытого ввода-вывода, в которой используется механизм асинхронного ввода-вывода функций чтения и записи для открытия 5 экземпляров канала.

Приложение 2

Листинг программы – простой клиент именованного канала

#include "stdafx.h"

#include <windows.h>

#include <stdio.h>

#include <conio.h>

#define PIPE_NAME "\\\\.\\Pipe\\Jim"

void main(void) {

    HANDLE PipeHandle;

    DWORD BytesWritten;

    DWORD BytesReaden;

char buffer[256];

    if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) == 0)

    {

              printf("WaitNamedPipe failed with error %d\n",

                       GetLastError());

              _getch();

              return;

    }

    if ((PipeHandle = CreateFile(PIPE_NAME,

              GENERIC_READ | GENERIC_WRITE, 0,

              (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING,

              FILE_ATTRIBUTE_NORMAL,

              (HANDLE) NULL)) == INVALID_HANDLE_VALUE)

    {

              printf("CreateFile failed with error %d\n", GetLastError());

                       _getch();

              return;

    }

    if (WriteFile(PipeHandle, "This is a test", 14, &BytesWritten,

              NULL) == 0)

    {

              printf("WriteFile failed with error %d\n", GetLastError());

              CloseHandle(PipeHandle);

                       _getch();

              return;

    }

    printf("Wrote %d bytes", BytesWritten);

    printf("\n");

    if (ReadFile(PipeHandle, buffer, 256, &BytesReaden,

              NULL) == 0)

    {

              printf("ReadFile failed with error %d\n", GetLastError());

              CloseHandle(PipeHandle);

                       _getch();

              return;

    }

printf("Read %d bytes\n",BytesReaden);

buffer[BytesReaden]='\0';

//  printf("Wrote %d bytes", BytesWritten);

printf(buffer);

printf("\n");

    CloseHandle(PipeHandle);

              _getch();

}

 

Листинг программы – простой сервер именованного канала

#include "stdafx.h"

#include <windows.h>

#include <stdio.h>

#include <conio.h>

void main(void)

{

    HANDLE PipeHandle;

    DWORD BytesRead;

    CHAR buffer[256];

DWORD BytesWritten;

    if ((PipeHandle = CreateNamedPipe("\\\\.\\Pipe\\Jim",

              PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1,

              0, 0, 1000, NULL)) == INVALID_HANDLE_VALUE)

    {

              printf("CreateNamedPipe failed with error %d\n",

                       GetLastError());

              return;

    }

 

    printf("Server is now running\n");

 

    if (ConnectNamedPipe(PipeHandle, NULL) == 0)

    {

              printf("ConnectNamedPipe failed with error %d\n",

                       GetLastError());

              CloseHandle(PipeHandle);

              _getch();

              return;

    }

 

    if (ReadFile(PipeHandle, buffer, sizeof(buffer),

              &BytesRead, NULL) <= 0)

    {

              printf("ReadFile failed with error %d\n", GetLastError());

 

              CloseHandle(PipeHandle);

              _getch();

              return;

    }

 

printf("Read %d bytes\n",BytesRead);

buffer[BytesRead]='\0';

//  printf("Wrote %d bytes", BytesRead);

    printf("\n");

 

printf(buffer);

printf("\n");

//  printf("%.*s\n", BytesRead, buffer);

    if (WriteFile(PipeHandle, "This is a snswer", 14, &BytesWritten,

              NULL) == 0)

    {

              printf("WriteFile failed with error %d\n", GetLastError());

              CloseHandle(PipeHandle);

                       _getch();

              return;

    }

printf("Wrote %d bytes", BytesWritten);

printf("\n");

    if (DisconnectNamedPipe(PipeHandle) == 0)

    {

              printf("DisconnectNamedPipe failed with error %d\n",

                       GetLastError());

              _getch();

              return;

    }

 

    CloseHandle(PipeHandle);

}

Листинг программы – усовершенствованный сервер именованного канала

#include <windows.h>

#include <stdio.h>

#include <conio.h>

#define NUM_PIPES 5

#define BUFFER_SIZE 256

 

void main(void)

{

    HANDLE PipeHandles[NUM_PIPES];

    DWORD BytesTransferred;

    CHAR Buffer[NUM_PIPES][BUFFER_SIZE];

    INT i;

    OVERLAPPED Ovlap[NUM_PIPES];

    HANDLE Event[NUM_PIPES];

 

    BOOL DataRead[NUM_PIPES];

    DWORD Ret;

    DWORD Pipe;

 

    for(i = 0; i < NUM_PIPES; i++)

    {

              if ((PipeHandles[i] = CreateNamedPipe("\\\\.\\PIPE\\jim",

                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,

                       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, NUM_PIPES,

                       0, 0, 1000, NULL)) == INVALID_HANDLE_VALUE)

              {

                       printf("CreateNamedPipe for pipe %d failed "

                                 "with error %d\n", i, GetLastError());

                       _getch();

                       return;

              }

 

              if ((Event[i] = CreateEvent(NULL, TRUE, FALSE, NULL))

                       == NULL)

              {

                       printf("CreateEvent for pipe %d failed with error %d\n",

                           i, GetLastError());

                       continue;

              }

              DataRead[i] = FALSE;

 

              ZeroMemory(&Ovlap[i], sizeof(OVERLAPPED));

              Ovlap[i].hEvent = Event[i];

              // Listen for client connections using ConnectNamedPipe()

              if (ConnectNamedPipe(PipeHandles[i], &Ovlap[i]) == 0)

              {

                       if (GetLastError()!= ERROR_IO_PENDING)

                       {

                                 printf("ConnectNamedPipe for pipe %d failed with",

                                 " error %d\n", i, GetLastError());

                                 CloseHandle(PipeHandles[i]);

                                 _getch();

                                 return;

                       }

              }

    }

 

    printf("Server is now running\n");

 

 

    while(1)

    {

              if ((Ret = WaitForMultipleObjects(NUM_PIPES, Event,

                       FALSE, INFINITE)) == WAIT_FAILED)

              {

                       printf("WaitForMultipleObjects failed with error %d\n",

                                 GetLastError());

                       _getch();

                       return;

              }

              Pipe = Ret - WAIT_OBJECT_0;

              ResetEvent(Event[Pipe]);

              if (GetOverlappedResult(PipeHandles[Pipe], &Ovlap[Pipe],

                       &BytesTransferred, TRUE) == 0)

              {

                       printf("GetOverlapped result failed %d start over\n",

                                 GetLastError());

                       if (DisconnectNamedPipe(PipeHandles[Pipe]) == 0)

                       {

                           printf("DisconnectNamedPipe failed with error %d\n",

                                          GetLastError());

                                 _getch();

                                 return;

                       }

                       if (ConnectNamedPipe(PipeHandles[Pipe],

                                 &Ovlap[Pipe]) == 0)

                       {

                                 if (GetLastError()!= ERROR_IO_PENDING)

                                 {

                                          // Severe error on pipe. Close this

                                          // handle forever.

              printf("ConnectNamedPipe for pipe %d failed with""error %d\n", i, GetLastError());

                                          CloseHandle(PipeHandles[Pipe]);

                                 }

                       }

                       DataRead[Pipe] = FALSE;

              }

              else

              {

                       if (DataRead[Pipe] == FALSE)

                       {

                                 ZeroMemory(&Ovlap[Pipe], sizeof(OVERLAPPED));

                                 Ovlap[Pipe].hEvent = Event[Pipe];

                                 if (ReadFile(PipeHandles[Pipe], Buffer[Pipe],

                                          BUFFER_SIZE, NULL, &Ovlap[Pipe]) == 0)

                                 {

                                          if (GetLastError()!= ERROR_IO_PENDING)

                                          {

                                                   printf("ReadFile failed with error %d\n",

                                                   GetLastError());

                                          }

                                 }

Buffer[Pipe][BytesTransferred]='\0';

printf("%s\n",Buffer[Pipe]);

                                 DataRead[Pipe] = TRUE;

                       }

                       else

                       {

                                     

                                 printf("Received %d bytes, echo bytes back\n",

                                          BytesTransferred);

                  //  _getch();

              //            DataRead[Pipe] = TRUE;

                                 ZeroMemory(&Ovlap[Pipe], sizeof(OVERLAPPED));

                                 Ovlap[Pipe].hEvent = Event[Pipe];

                                 if (WriteFile(PipeHandles[Pipe], "Stop",

                                 BUFFER_SIZE, NULL, &Ovlap[Pipe]) == 0)

                                 {

                                          if (GetLastError()!= ERROR_IO_PENDING)

                                          {

                                                   printf("WriteFile failed with error %d\n",

                                                   GetLastError());

                                          }

                                 }

                                 DataRead[Pipe] = FALSE;

                              }

                   }

       }                     

}

 


Поделиться с друзьями:

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.357 с.