Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практичне заняття № 5 МЗКІТ (10 ТП).DOCX
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
3 Мб
Скачать
☆

11.6.3. Поіменовані канали

Пойменовані канали POSIX

Поіменовані канали POSIX є однобічним засобом передавання даних. Це означає, що якщо один процес записує дані в канал, то інший із цього каналу може тільки читати, причому читання даних відбувається в порядку їхнього записування за принципом FIFO.

Поіменовані канали відображені спеціальними FIFO-файлами у файловій системі UNIX. За іменем такого файла до поіменованого каналу може підключитися будь-який процес у системі, у якого є права читання з цього файла. Після цього всі дані, передані в канал, надходитимуть цьому процесу', поки канал не буде закрито. Для створення FIFO-файла у POSIX передбачена функція mkfifo( ):

Першим параметром nkfifo( ) приймає повний шлях до створюваного файла, другим - режим (аналогічно до першого і третього параметрів open( )). Ось приклад створення поіменованого каналу:

Після того як канал (FIFO-файл) створено, будь-який процес може підключитися до нього. Для цього він має спочатку створити з’єднання із каналом за допомогою виклику open( ). При цьому процес буде заблокований для очікування даних від іншого процесу (у разі читання із каналу очікування триватиме доти, поки інший процес не запише у канал, у разі записування — доки не буде виконане читання). Після закінчення очікування процес може записувати дані в канал за допомогою write( ) або зчитувати їх із каналу за допомогою read( ):

Розглянемо найпростіший підхід до обміну даними через поіменований канал (коли клієнти посилають на сервер повідомлення).

Для цього на сервері потрібно виконати такий код:

У разі закриття сервера (наприклад, за сигналом) необхідно закрити канал і вилучити файл каналу за допомогою unlink( ). Наведемо код клієнта:

Поіменовані канали Win32 АРІ

На відміну від каналів POSIX, поіменовані канали Win32 реалізують двобічний обмін повідомленнями і не використовують прямо файли на файловій системі. Однак їхнє використання ґрунтується на схожих принципах.

Імена таких каналів створюють за такою схемою:

Для доступу до каналу на локальному комп’ютері замість імені машини можна використовувати символ «.»: \\.\ріре\ім'я_каналу. Такі імена називають UNC-іменами (Universal Naming Convention — універсальна угода з імен); про них докладно йтиметься пізніше.

Для створення екземпляра каналу на сервері використовують функцію CreateNamedPipe( ):

де: pname — ім’я каналу на локальному комп’ютері (на віддалених комп’ютерах створювати канали не можна);

openmode - режим відкриття каналу (наприклад, вмикання прапорця РІРЕ_АС- CESS_DUPLEX означає двобічний зв’язок);

pipemode — режим обміну даними із каналом (наприклад, для побайтового читання із каналу потрібно увімкнути прапорець PIPE£_READMODE_BYTE, для побайтового записування - PIPE_TYPE_BYTE);

max_conn - максимальна кількість клієнтських з’єднань із цим каналом (необмежену кількість задають як PIPE_UNLIMITED_INSTANCES);

timeout — максимальний час очікування клієнтом доступу до цього каналу (необмежене очікування задають як NMPWAIT_WAIT_FOREVER).

CreateNamedPipe( ) повертає дескриптор створеного каналу:

Для очікування клієнтського з’єднання необхідно виконати функцію ConnectNamedРіре( ):

Як тільки клієнт підключиться до цього каналу, очікування буде завершене, і можна читати з каналу або записувати в канал за допомогою ReadFile( ) і WriteFile( ). Після завершення обміну даними сервер закриває з’єднання, викликавши функцію DisconnectNamedPiре( ).

Після завершення роботи із каналом (наприклад, у разі виходу із програми) його дескриптор потрібно закрити за допомогою CloseHandlе( ).

Наведемо код сервера, аналогічний за функціональністю до прикладу для поіменованих каналів POSIX.

При розробці коду клієнта, необхідно:

♦ викликати функцію WaitNamedPipe( ), що очікуватиме виконання сервером ConnectNamedPipe( );

♦ після того, як очікування завершене, встановити з’єднання із каналом за допомогою CreateFile( );

♦ виконати обмін даними за допомогою ReadFiІе( ) і WriteFiІе( ), використовуючи дескриптор з’єднання, повернений CreateFile( );

♦ закрити дескриптор каналу за допомогою CloseHandle( ):

Зауважимо, що у функції WaitNamedPipe( ) і CreateFilе( ) можна передавати імена каналів, розміщених на віддалених комп’ютерах.