Соединение клиентов с именованным каналом

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

BOOL WaitNamedPipe (

LPCTSTR lpNamedPipeName, // указатель на имя канала

DWORD nTimeOut // интервал ожидания

);

которая в случае успешного завершения возвращает значение TRUE, а в случае неудачи – FALSE. Параметры этой функции имеют следующие значения.

Параметр lpNamedPipeName указывает на строку, которая должна иметь вид

\\<server_name>\pipe\<pipe_name>

Здесь <server_name> обозначает имя компьютера, на котором выполняется сервер именованного канала.

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

· NMPWAIT_USE_DEFAULT_WAIT интервал времени ожидания определяется значением параметра nDefaultTimeOut, который задается в функции CreateNamedPipe,

· NMPWAIT_WAIT_FOREVER бесконечное время ожидания связи с именованным каналом.

Сделаем два важных замечания относительно работы функции WaitNamedPipe. Во-первых, если не существует экземпляров именованного канала с именем lpNamedPipe, то эта функция немедленно завершается неудачей, независимо от времени ожидания, заданного параметром nTimeOut. Во-вторых, если клиент соединяется с каналом до вызова сервером функции ConnectNamedPipe, то функция WaitNamedPipe возвращает значение FALSE и функция GetLastError вернет код ERROR_PIPE_CONNECTED. Поэтому функцию WaitNamedPipe нужно вызывать только после соединения сервера с каналом посредством функции ConnectNamedPipe.

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

HANDLE CreateFile (

LPCTSTR lpFileName, // указатель на имя канала

DWORD dwDesiredAccess, // чтение или запись в канал

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

LPSECURITY_ATTRIBUTES lpSecurityAttributes, // атрибуты защиты

DWORD dwCreationDisposition, // флаг открытия канала

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

HANDLE hTemplateFile // дополнительные атрибуты

);

которая в случае успешного завершения возвращает дескриптор именованного канала, а в случае неудачи – значение INVALID_HANDLE_VALUE.

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

Параметр lpFileName должен указывать на имя канала, которое должно быть задано в том же формате, что и в функции WaitNamedPipe.

Параметр dwDesiredAccess может принимать одно из следующих значений:

· 0 разрешает получить атрибуты канала,

· GENERIC_READ разрешает чтение из канала,

· GENERIC_WRITE разрешает запись в канал.

Следует отметить, что функция CreateFile завершается неудачей, если доступ к именованному каналу, заданный этими значениями, не соответствует значениям параметра dwOpenMode в функции CreateNamedPipe. Кроме того, в этом параметре программист может определить стандартные права доступа к именованному каналу. За более подробной информацией по этому вопросу нужно обратиться к MSDN.

Параметр dwShareMode определяет режим совместного использования именованного канала и может принимать значение 0, которое запрещает совместное использование именованного канала или любую комбинацию следующих значений:

· FILE_SHARE_READ разрешает совместное чтение из канала,

· FILE_SHARE_WRITE разрешает совместную запись в канал.

Параметр lpSecurityAttributes задает атрибуты защиты именованного канала.

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

Для именованного канала параметр dwFlagsAndAttributes можно задается равным 0, что определяет флаги и атрибуты по умолчанию. Подробную информацию о значениях этого параметра смотри в MSDN.

Значение параметра hTemplateFile задается равным NULL.

Сделаем следующие замечания относительно работы с функцией CreateFile в случае её использования для открытия доступа к именованному каналу. Во-первых, несмотря на то, что функция WaitNamedPipe может успешно завершиться, последующий вызов функции CreateFile может завершиться неудачей по следующим причинам:

между вызовами этих функций сервер закрыл канал,

между вызовами функций другой клиент связался с экземпляром этого канала.

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

Кроме того, следует отметить, что если клиент работает на той же машине, что и сервер и использует для открытия именованного канала в функции CreateFile имя сервера в виде:

\\.\pipe\<pipe_name>

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

\\<server_name>\pipe\<pipe_name>

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


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: