Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Теоретические сведения. Windows API предоставляет еще один способ взаимодействия между процессами – именованные каналы, которые позволяют обмениваться в симплексном или дуплексном



Windows API предоставляет еще один способ взаимодействия между процессами – именованные каналы, которые позволяют обмениваться в симплексном или дуплексном режиме байтовым потоком данных не только между процессами на одной машине, но и на разных машинах в локальной сети.

Именованный канал может работать в двух режимах:

Именованный канал создается на стороне сервера с помощью функции:

HANDLE WINAPI CreateNamedPipe(LPCTSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes);

Параметры

lpName имя канала. Это имя будет использовано для доступа к проекции из другого процесса. Имя должно быть записано в следующем виде: \\.\pipe\имяканала «имяканала» может содержать любые символы, кроме обратного слеша. Общая длина имени не должна превышать 256 символов. Имена каналов не чувствительны к регистру.
dwOpenMode флаги именованного канала. Должен как минимум содержать режим доступа к каналу (один из трех): PIPE_ACCESS_DUPLEX – дуплексный канал; PIPE_ACCESS_INBOUND – симплексный канал от клиента к серверу PIPE_ACCESS_OUTBOUND – симплексный канал от сервера к клиенту и также может содержать необязательные флаги в том числе: FILE_FLAG_WRITE_THROUGH – режим сквозной записи. Если клиент и сервер находятся на разных машинах, то операция записи не вернет управление, пока данные не будут переданы по сети и не будут помещены во входные буферы канала на конечном узле.
dwPipeMode режим работы канала – состоит из нескольких групп флагов: 1) режим записи данных: PIPE_TYPE_BYTE – данные поступают в канал в виде потока байтов (не может быть использован одновременно с PIPE_READMODE_MESSAGE); PIPE_TYPE_MESSAGE – данные поступают в канал в виде потока сообщений. 2) режим чтения данных: PIPE_READMODE_BYTE – данные читаются в виде поток байтов; PIPE_READMODE_MESSAGE – данные читаются в виде пока сообщений. 3) PIPE_WAIT – операция чтения/записи блокирует поток до завершения операции и ряд других флагов.
nMaxInstances максимальное число экземпляров именованного канала с указанным именем. От 1 до PIPE_UNLIMITED_INSTANCES (255). Если указать PIPE_UNLIMITED_INSTANCES, то число экземпляров не ограничено (точнее ограничено системными ресурсами).
nOutBufferSize размер выходного буфера в байтах
nInBufferSize размер входного буфера в байтах
nDefaultTimeOut время тайм-аута по умолчанию в миллисекундах
lpSecurityAttributes указатель на структуру SECURITY_ATTRIBUTES – параметры безопасности именованного канала. Чтобы присвоить атрибуты защиты по умолчанию, передайте в этом параметре NULL.
результат функции Дескриптор объекта ядра или INVALID_HANDLE_VALUE – в этом случае подробности об ошибке можно получить с помощью GetLastError()

Размер входных и выходных буферов является ориентировочным, фактическое значение система выберет сама. Буферы нужны для того, чтобы сохранять поступающие данные, если в данный момент сервер или клиент не могут их прочитать. В случае заполнения буфера система может расширить его размер, либо приостановить передачу данных с соответствующей стороны (соответственно поток на той «стороне» будет приостановлен).

После того как канал создан, сервер вызывает функции ожидания подключения клиента к каналу:

BOOL WINAPI ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped);

Параметры

hNamedPipe дескриптор объекта «именованный канал»
lpOverlapped нами не используется (применяется для неблокирующих операций чтения/записи)
результат функции Если не равно 0 – клиент успешно подключен. Если равно 0 – произошла ошибка, подробности об ошибке можно получить с помощью GetLastError(). Однако, если клиент выполнит попытку подключения в промежуток между CreateNamedPipe (либо DisconnectNamedPipe) и ConnectNamedPipe, тогда результат будет нулевым, а GetLastError() вернет ERROR_PIPE_CONNECTED – эта ситуация не является ошибочной и должна явным образом обрабатываться программистом.

В случае успешного подключения экземпляр объекта «именованный канал», переданный через параметр hNamedPipe, будет связан исключительно для обмена данными только с тем клиентом, для которого и было произведено подключение. Для того чтобы другие клиенты могли подключаться, необходимо создать новый экземпляр именованного канала (функция CreateNamedPipe – здесь становится ясен смысл параметра nMaxInstances) и поставить его на ожидание подключения с помощью ConnectNamedPipe.

Подключенный экземпляр теперь может передавать/получать данные между сервером и клиентом с помощью функции чтения/записи из файла – это ReadFile и WriteFile (подробности далее). По завершении сеанса сервер либо закрывает экземпляр канал с помощью функции CloseHandle – при этом экземпляр уничтожается, либо отсоединяет клиента от экземпляра канала с помощью функции DisconnectNamedPipe:

BOOL WINAPI DisconnectNamedPipe(HANDLE hNamedPipe);

Параметры

hNamedPipe дескриптор объекта «именованный канал»
результат функции Если не равно 0 – клиент успешно отключен. Если равно 0 – произошла ошибка, подробности об ошибке можно получить с помощью GetLastError().

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

Со стороны клиента для подключения к именованному каналу необходимо использовать функцию CreateFile:

HANDLE WINAPI CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);

Параметры (для работы с именованными каналами):

lpFileName имя канала. Имя должно быть записано в следующем виде: \\имясервера\pipe\имяканала «имясервера» - имя компьютера, где расположен сервер. Если это локальный компьютер, то можно указать точку – «.».
dwDesiredAccess доступ к объекту: GENERIC_READ – на чтение GENERIC_WRITE – на запись
dwShareMode режим разделения – укажите 0
lpSecurityAttributes указатель на структуру SECURITY_ATTRIBUTES – параметры безопасности именованного канала. Чтобы присвоить атрибуты защиты по умолчанию, передайте в этом параметре NULL.
dwCreationDisposition указание что делать, если объект существует. В нашем случае – это OPEN_EXISTING – требовать существование именованного канала.
dwFlagsAndAttributes флаги и атрибуты. В нашем случае – это 0.
hTemplateFile файл-шаблон. В нашем случае – это NULL
результат функции Дескриптор объекта ядра или INVALID_HANDLE_VALUE – в этом случае подробности об ошибке можно получить с помощью GetLastError()

Если на момент вызова именованный канал существует, но все его экземпляры заняты, CreateFile вернет INVALID_HANDLE_VALUE, а GetLastError() вернет ERROR_PIPE_BUSY. В этом случае клиент должен выполнить ожидание свободного экземпляра канала с помощью функции:

BOOL WINAPI WaitNamedPipe(LPCTSTR lpNamedPipeName, DWORD nTimeOut);

Параметры

lpNamedPipeName имя канала
nTimeOut время тайм-аута ожидания в миллисекундах. Можно также укать следующие константы: NMPWAIT_USE_DEFAULT_WAIT – использовать тайм-аут по умолчанию, указанный при создании канала функцией CreateNamedPipe; NMPWAIT_WAIT_FOREVER – не возвращать управление, пока не станет доступен экземпляр канала
результат функции Если не равно 0 – экземпляр доступен. Если равно 0 – экземпляр не доступен, подробности об ошибке можно получить с помощью GetLastError().

Объект именованного канала, полученный от функции CreateFile имеет режим байтового чтения без сквозной записи. Чтобы изменить параметры объекта нужно использовать функцию SetNamedPipeHandleState:

BOOL WINAPI SetNamedPipeHandleState(HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout);

Параметры

hNamedPipe дескриптор объекта «именованный канал»
lpMode режим работы канала – состоит из нескольких групп флагов: 1) режим чтения данных: PIPE_READMODE_BYTE – данные читаются в виде поток байтов; PIPE_READMODE_MESSAGE – данные читаются в виде пока сообщений. 2) PIPE_WAIT – операция чтения/записи блокирует поток до завершения операции
lpMaxCollectionCount укажите NULL
lpCollectDataTimeout укажите NULL
результат функции Если не равно 0 – клиент успешно подключен. Если равно 0 – произошла ошибка, подробности об ошибке можно получить с помощью GetLastError().

Ядро удаляет объект «именованный канал» после того как счетчик ссылок на объект станет равным нулю.

Чтение/запись в именованный канал

Чтение из именованного канала производится с помощью функции ReadFile:

BOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);

Параметры

hFile дескриптор объекта «именованный канал»
lpBuffer указатель на область памяти, куда поместить прочитанные данные
nNumberOfBytesToRead сколько байт нужно прочитать
lpNumberOfBytesRead указатель на переменную, в которую будет помещено число фактически прочитанных байт
lpOverlapped в нашем случае не используется = NULL
результат функции Если не равно 0 – функция успешно выполнилась. Если равно 0 – произошла ошибка, подробности об ошибке можно получить с помощью GetLastError(). В случае если размер отправленного сервером сообщения не помещается в буфер пользователя, данные будут прочитаны до размера буфера, GetLastError() вернет ERROR_MORE_DATA, и пользователю необходимо прочесть остаток данных с помощью ReadFile.

Запись в именованный канал производится с помощью функции WriteFile:

BOOL WINAPI WriteFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);

hFile дескриптор объекта «именованный канал»
lpBuffer указатель на область памяти, где находятся данные для записи
nNumberOfBytesToWrite сколько байт нужно записать
lpNumberOfBytesWritten указатель на переменную, в которую будет помещено число фактически записанных байт
lpOverlapped в нашем случае не используется = NULL
результат функции Если не равно 0 – функция успешно выполнилась. Если равно 0 – произошла ошибка, подробности об ошибке можно получить с помощью GetLastError().

Windows API предоставляет функцию, которая ориентирована на работу с именованными каналами в режиме передачи сообщений, она выполняет запись сообщения и ждет ответа от сервера:

BOOL WINAPI TransactNamedPipe(HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped);

Параметры





Дата публикования: 2015-10-09; Прочитано: 323 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.008 с)...