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

Теоретические сведения. 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);

Параметры

hNamedPipe дескриптор объекта «именованный канал»
lpInBuffer указатель на данные для отправки на сервер
nInBufferSize размер данных для отправки
lpOutBuffer указатель на область памяти, куда помещать ответ
nOutBufferSize размер области памяти для ответа
lpBytesRead размер полученных данных
lpOverlapped не используется
результат функции Если не равно 0 – функция успешно выполнилась. Если равно 0 – произошла ошибка, подробности об ошибке можно получить с помощью GetLastError(). В случае если размер отправленного сервером сообщения не помещается в буфер пользователя, данные будут прочитаны до размера буфера, GetLastError() вернет ERROR_MORE_DATA, и пользователю необходимо прочесть остаток данных с помощью ReadFile.




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



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