Реферат: План нмв 2004 р. Укладачі



Державний комітет зв’язку та інформатизації України

—————————————————

ОДЕСЬКА НАЦІОНАЛЬНА АКАДЕМІЯ ЗВ’ЯЗКУ ім. О. С. Попова


Кафедра обчислювальної техніки та мікропроцесорів


Створення програмного забезпечення телекомунікацій

для роботи в ОС UNIX


Методичний посібник

до лабораторних робіт № 15 — 19

з дисципліни

“Системне та прикладне програмне забезпечення в телекомунікаціях”

для спеціальності 7.092402


Одеса 2004


Державний комітет зв’язку та інформатизації України

—————————————————

^ ОДЕСЬКА НАЦІОНАЛЬНА АКАДЕМІЯ ЗВ’ЯЗКУ ім. О. С. Попова


Кафедра обчислювальної техніки та мікропроцесорів


Створення програмного забезпечення телекомунікацій

для роботи в ОС UNIX


Методичний посібник

до лабораторних робіт № 15 — 19

з дисципліни

“Системне та прикладне програмне забезпечення в телекомунікаціях”

для спеціальності 7.092402


ЗАТВЕРДЖЕНО

методичною радою академії

Протокол № 8

від 9.03.2004 р.


Одеса 2004


УДК 681.3.06

План НМВ 2004 р.


Укладачі — С. П. Главацький

І. В. Хіхловська


Рецензент — О. В. Онацький


Методичний посібник “Створення програмного забезпечення телекомунікацій для роботи в ОС UNIX” до лабораторних робіт № 15 — 19 спрямований на ознайомлення студентів з основними способами взаємодії процесів в мережі в середовищі ОС UNIX; містить основні положення щодо створення, налагодження та ведення програмного забезпечення мережних додатків, а також опис інструментів та ресурсів налаштування мереж, мережних додатків та обліку трафіка. Наведені домашні завдання та форма звітності до кожної з лабораторних робіт.


СХВАЛЕНО

на засіданні кафедри

обчислювальної техніки

та мікропроцесорів

і рекомендовано до друку

Протокол № 4

від 18.12.2003 р.


ЗМІСТ


1 Лабораторна робота № 15 Взаємодія процесів в ОС UNIX за допомогою

іменованих каналів 4

2 Лабораторна робота № 16 Взаємодія процесів в ОС UNIX за допомогою

інтерфейсу сокетів 12

3 Лабораторна робота № 17 Програмна реалізація протоколів ТСР/ІР 24

4 Лабораторна робота № 18 Інструменти та ресурси налагодження мереж та

мережних додатків 30

5 Лабораторна робота № 19 Створення системи обліку трафіка 46

Додаток А Тексти програм serverfifo та clientfifo 56

Додаток Б Тексти програм socketserver та socketclient 58

Додаток В Тексти програм servertcp та clienttcp 60

Додаток Г Тексти програм simpletcpserv та simpletcpclient 63

Додаток Д Лістинг програми обліку трафіка 65


Лабораторна робота № 15


^ ВЗАЄМОДІЯ ПРОЦЕСІВ В ОС UNIX ЗА ДОПОМОГОЮ ІМЕНОВАНИХ КАНАЛІВ

1 Мета роботи


Метою роботи є вивчення взаємодії процесів у ОС UNIX за допомогою різних засобів, набуття навичок написання, налагоджування та ведення програм взаємодії процесів за допомогою іменованих каналів у ОС UNIX.


^ 2 Основні положення


2.1 Способи забезпечення взаємодії процесів в ОС UNIX


В ОС UNIX процеси виконуються у власних адресних просторах і є ізольовані один від одного; тим самим зведено до мінімуму можливості впливу процесів один на одного, що є надто важливим у багатозадачних ОС, однак власне концепція UNIX ґрунтується на модульному принципі й передбачає взаємодію поміж процесами.

Взаємодія поміж процесами необхідна для розв’язування таких завдань:

1 Передавання даних; їхній обсяг може коливатись від десятків байтів до кількох мегабайтів.

2 Спільне використання даних; процеси можуть використовувати спільно одну копію даних, причому зміни, внесені одним процесом, відразу будуть помітні для іншого. Кількість взаємодіючих процесів може бути більшою за два. З метою збереження цілісності ресурсів процесам може потребуватись протокол взаємодії для збереження цілісності даних та виключення конфліктів при доступі до них.

3 Повідомлення використовуються, коли один процес має сповістити інший про певну подію, наприклад для синхронізування кількох процесів. Розв’язується ця задача засобами ОС, тому що власне самі процеси у рамцях багатозадачної ОС діяли б неефективно і навіть небезпечно.

До засобів міжпроцесної взаємодії, притаманних усім версіям UNIX, належать:

сигнали;

канали;

іменовані канали FIFO;

повідомлення та їх черги;

семафори;

розподілювана пам’ять;

сокети.

Використання сигналів обмежується сферою повідомлень про помилки, але вони можуть використовуватись і для синхронізування процесів, передавання простіших команд від одного процесу до іншого. Сигнали є надто ресурсоємні, малоінформативні й їхню кількість обмежено.

Канали може бути зорганізовано при роботі у командному рядку shell:

cat myfile |wc.

Стандартне виведення програми cat(1), яка виводить вміст файла myfile, передається на стандартний ввід програми wc(1), яка, у свою чергу, підраховує кількість рядків, слів та символів. Як наслідок на екран монітора буде виведено дані:

12 45 260,

що означає кількість рядків, слів та символів у файлі myfile. Отже, два процеси обмінялися даними. Програмний канал забезпечує односпрямоване передавання даних поміж двома процесами.

Для створення каналу використовується системний виклик pipe(2)

int pipe(int *filedes),

який повертає два файлових дескриптори: filedes[0] — для запису до каналу та filedes[1] — для читання з каналу. Якщо один процес записує дані до filedes[0], інший може отримати ці дані з filedes[1]. При створюванні процесу атрибути батьківського процесу наслідуються дочірнім процесом, у тому числі файлові дескриптори. Доступ до дескрипторів filedes каналу може отримати сам процес, що він викликав pipe(2), та його дочірні процеси. Отже, канали може бути використано для передавання даних лише поміж родинними процесами, а для міжпроцесної взаємодії поміж незалежними процесами не використовуються.

У наведеному прикладі обидва процеси, cat(1) та wc(1), створюються процесом shell і тому є родинними, хоча на перший погляд здаються незалежними.

^ Повідомлення та їхні черги є складовою частиною UNIX System V, вони обслуговуються ОС, розміщуються в адресному просторі ядра і є розподілюваним системним ресурсом. Кожна черга має свій унікальний ідентифікатор, а процеси можуть записувати та зчитувати повідомлення з різних черг. Процес, що він надсилає повідомлення до черги, може не очікувати на читання цього повідомлення певним іншим процесом. Він може завершити своє виконання, залишивши у черзі повідомлення, яке буде прочитане іншим процесом пізніше. Це надає можливість процесам обмінюватись структурованими даними, які мають атрибути:

тип повідомлення; повідомлення в одній черзі можуть бути мультиплексовані;

довжина даних повідомлення у байтах (може бути нульовою);

власне дані; за ненульової довжини вони можуть бути структурованими.

Процес може розміщувати у черзі повідомлення за допомогою функції msgsnd(2), отримувати повідомлення певного типу з черги за допомогою msgrcv(2), керувати повідомленнями за допомогою функції msgctl(2).

Типова є ситуація взаємодії процесів, коли серверний процес обмінюється даними з кількома клієнтами, виглядає таким чином: в одній черзі можна мультиплексувати повідомлення від різних процесів, що дозволяє виконувати для обміну одну чергу, але кожному з повідомлень, спрямованих від будь-якого клієнта серверові, треба надавати значення типу, наприклад, 1; якщо в тілі повідомлення клієнт певним чином ідентифікує себе, наприклад передає свій PID, то сервер може переспрямовувати повідомлення конкретному клієнтові, привласнюючи тип повідомлення дорівнюваним цьому ідентифікаторові, функція msgrcv(2) дозволяє приймати повідомлення певного типу, тому сервер прийматиме повідомлення з типом 1, а клієнти — повідомлення з типами, що вони дорівнюють ідентифікаторам їхніх клієнтів.

Семафори використовуються для синхронізування доступу кількох процесів до розподілюваних ресурсів. Вони виконують функцію дозволу або заборони процесу використання того чи того розподілюваного ресурсу. Семафори є системним ресурсом, дії над яким зреалізовуються через інтерфейс системних функцій і не призначені для обміну потужними обсягами даних. UNIX припускає три можливі операції над семафором, що вони визначаються системним викликом semop(2), а саме його полем semop

int semop(int semid, struct sembuf *semop, size_t nops):

1 якщо величина semop додатна, поточне значення семафора збільшується на цю величину;

2 якщо значення semop дорівнює нулю, процес очікує, допоки семафор не обнулиться;

3 якщо значення semop є від’ємне, процес очікує, допоки значення семафора не збільшиться або не дорівнюватиме абсолютному значенню semop, після чого це значення віднімається від значення семафора.

Перша операція змінює значення семафора безумовно, друга — лише перевіряє його значення, тобто зреалізовується умовне виконання, третя — перевіряє й змінює значення семафора — умовне виконання операції. Наведений приклад є прикладом кооперативно виконуваних семафорів як функцій ОС: взаємодіючі процеси мають домовлятися щодо їхнього використання. ОС не накладає жодних обмежень на використання семафорів, зокрема процеси самі вирішують, яке значення семафора є таким, що дозволяє, на яку величину зміниться значення семафора тощо. Інтенсивний обмін даними поміж процесами за допомогою каналів та черг повідомлень може зменшити продуктивність системи. Це пов’язано з тим, що дані, передавані за допомогою цих об’єктів, копіюються з буфера передавального процесу у буфер ядра, а потім — у буфер приймального процесу.

^ Розподілювану пам’ять зорганізовано у такий спосіб, який надає двом чи більшій кількості процесів можливість безпосереднього доступу до однієї області пам’яті для обміну даними. Безумовно, процеси мають попередньо “домовитись” щодо правил використання розподілюваної пам’яті. Наприклад, допоки один з процесів записує дані до розподілюваної пам’яті, решта процесів мають утримуватись від роботи з нею. Завдання кооперативного використовування розподілюваної пам’яті розв’язується за допомогою синхронізування виконання процесів засобами семафорів. Сценарій роботи з розподілюваною пам’яттю має вигляд:

1 Сервер отримує доступ до розподілюваної пам’яті, використовуючи семафор.

2 Сервер записує дані у розподілювану пам’ять.

3 Після завершення запису сервер звільнює розподілювану пам’ять за допомогою семафора.

4 Клієнт отримує доступ до розподілюваної пам’яті й закриває доступ до ресурсу за допомогою семафора.

5 Клієнт читає дані з розподілюваної пам’яті, відкриваючи доступ до ресурсу, використовуючи семафор.

Кілька процесів можуть відбивати області розподілюваної пам’яті на різні ділянки власного віртуального адресного простору. Розподілювана пам’ять є найбільш швидкий та найменш ресурсоємний спосіб взаємодії процесів.

Сокети — це спеціальні об’єкти, які позначають комунікаційний вузол, котрий забезпечує приймання та передавання даних для процесу.


^ 2.2 Взаємодія поміж процесами за допомогою іменованих каналів


Назва каналів FIFO походить від абревіатури висловлювання FIRST IN FIRST OUT (перший увійшов, перший вийшов). FIFO є надто схожі на канали, вони є односпрямованим засобом передавання даних, причому читання даних відбувається у тому ж самому порядку, що й записування. На відміну від програмних каналів, вони мають імена, які дозволяють незалежним програмам отримати доступ до цих об’єктів. FIFO є засобом версії UNIX System V і для використання в інших версіях потребують встановлення додаткових бібліотек системних викликів.

FIFO є окремим типом файла у файловій системі UNIX (результат виконання команди ls –l покаже символ р у першій позиції). Для створення FIFO використовується системний виклик mkfifo(2):

int mkfifo(char *pathname, int mode),

де: pathname — ім’я файла у файловій системі (ім’я FIFO),

mode — прапорці володіння, прав доступу тощо.

FIFO може бути створено і з командою рядка shell:

$ mkfifo name p

Після створення FIFO може бути відкрито на записування та читання, причому записування та читання можуть відбуватися в різних незалежних процесах. Канали FIFO та звичайні канали працюють за такими правилами:

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

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

3 Якщо канал є порожній і жоден процес не відкрив його на записування, системний виклик read(2) буде заблоковано до з’явлення даних (якщо лише для каналу або FIFO не встановлено прапорець відсутності блокування O_NDELAY).

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

5 У перебігу запису більшої кількості байтів, аніж це дозволяє канал або FIFO, виклик write(2) блокується до звільнення потрібного місця, але атомарність цієї операції не гарантується. Якщо процес намагається записати дані до каналу, не відкриваного жодним процесом, процесові генерується сигнал SIGPIPE, а виклик write(2) повертає 0 із встановленням помилки (errno = EPIPE). Якщо процес не встановив опрацьовування сигналу SIGPIPE, опрацьовування відбувається за умовчанням — процес завершується.

У каналі може перебувати лише певна кількість байтів, перш ніж наступний виклик write(2) буде заблоковано. Мінімальний розмір каналу, визначений POSIX, дорівнює 512 байтів. Виклик write(2) виконується неподільними порціями, і запис виконується ядром за одну неперервну операцію. Батьківський процес виконується у нескінченному циклі, а дочірній надсилає повідомлення батьківському, опитуючи канал і перевіряючи, чи надійшли дані.

Буферізація даних у каналі стандартно зреалізовується шляхом відокремлювання дискового простору у структурі файлової системи. Отже, запис та читання пов’язані з дисковим введенням/виведенням, що зменшує його продуктивність. Сучасні серверні ОС забезпечують роботу каналів через спеціальну файлову систему HPPS (High Performance Pipe System). З її допомогою дані буферизуються в оперативній пам’яті, що прискорює запис/читання.


^ 2.3 Функції та системні виклики ОС UNIX,

потрібні для створювання іменованих каналів


1 Функція pipe(2) створює односпрямований канал (симплексний) для анонімного обміну даними поміж двома спорідненими процесами, позаяк лише вони можуть отримати доступ до одного й того самого каналу. Після завершення роботи канал знищується. Функція має вигляд

#include

int pipe(int filedes[2])

Функція повертає два файлових дескриптори fd у масиві fd[0] та fd[1]; filedes[0] дозволяє читання даних з каналу, а filedes[1] використовується для записування даних у канал.

2 Функція fcntl(2) забезпечує керування файловими операціями у вже відкритих файлах, заданих дескрипторами файла — filedes.

#include < fcntl.h> — заголовний файл, у якому визначено цілі константи: O_RDONLY (для решти лише читати), O_WRONLY (для решти лише писати), O_RDWR (для решти читати та писати), які встановлюють або знімають блокування на файли чи їхні частки.

int fcntl (int filedes, int cmd, …) — функція fcntl(2) виконує дію, зазначену в cmd, з файлом, а третій аргумент залежить від конкретної дії:

а) F_SETLK — встановити блокування запису файла; структура flock описує блокування, а покажчик на неї передається у третьому аргументі; за неможливості блокування fcntl(2) повертається з помилкою EACCESS або EAGAIN.

б) F_SETLKW — аналогічний до попереднього, але аргумент використовується за неможливості блокування, якщо запис вже заблоковано; процес переходить до стану сну, очікуючи на зняття блокування (W_WAIT, очікувати).

в) F_SETFL — визначає режим запису даних наприкінці файла.

3 Функція printf(2) — запис до форматизованого стандартного виводу.

4 Системний виклик unlink(2) вилучає файл, наприклад unlink(“/tmp/usedfile”); виклик повертає 0 у разі успішного завершення та -1 — у разі помилки.

5 Системний виклик read(2) копіює довільну кількість символів чи байтів з файла до буфера (в ASCII кодах).

6 Системний виклик open(2) відкриває файл для читання, запису або створює порожній файл.

7 Системний виклик close(2) закриває файл, повертає його в разі успішного завершення та -1 — у разі помилки:

#include

int close (int filedes)

filedes = open(“file”, O_RDONLY);







close (filedes);

8 Системний виклик write(2) — копіює дані з буфера програми, що трактується як масив, до зовнішнього файла. Він, як і read(2), має три аргументи: дескриптор файла filedes, покажчик на записувані дані buffer та n — додатне число, котре визначає кількість записуваних байтів.

#include

ssize_t write(int filedes, const void *buffer, size_t n).

У додатку А наведено тексти програм “Сервера” та “Клієнта”, які зреалізовують взаємодію процесів за допомогою іменованих каналів FIFO. Клієнт за традицією надсилає серверові повідомлення “Dobryj denj, Svite!”, а сервер виводить це повідомлення на термінал. Програми написано мовою С.


^ 3 Контрольні запитання


1 З якою метою взаємодіють поміж собою процеси?

2 За допомогою яких засобів взаємодіють поміж собою процеси у всіх версіях UNIX?

3 Взаємодію поміж якими процесами можуть забезпечити канали?

4 Які атрибути має системний виклик mkfifo(2)?

5 За якими правилами працюють канали та іменовані канали?

6 Чим відрізняється FIFO від звичайного каналу?

7 Яку функцію виконує системний виклик unlink(2)?

8 Що зреалізовує функція fcntl(2)?


^ 4 Домашнє завдання


1 Відповісти на контрольні запитання у письмовій формі.

2 Переписати до протоколу тексти обох програм та зробити до них коментарі.

3 Змінити в програмі клієнта текст передаваного повідомлення на власне прізвище, ім’я та по-батькові, змінивши водночас необхідні параметри; пояснити ці зміни.


^ 5 Лабораторне завдання


1 Підімкніться до комп’ютера під керуванням ОС UNIX за допомогою telnet (“Пуск\Виконати\telnet ip”, де ip — адреса машини під керуванням UNIX).

2 Після підімкнення введіть ім’я (login) та пароль (password) згідно з таблицею 5.1.


Таблиця 5.1 — Імена та паролі

login

st1

st2

st3

st4

st5

st6

st7

st8

st9

password

st1

st2

st3

st4

st5

st6

st7

st8

st9

login

st11

st12

st13

st14

st15

st16

st17

st18

st19

password

st11

st12

st13

st14

st15

st16

st17

st18

st19


3 Створіть текстові файли serverfifo.c та clientfifo.c у редакторі ее, вихідні тексти цих файлів розміщено у додатку А (Лістинг 1 та Лістинг 2).

Для цього треба набрати:

ee serverfifo.c на першому терміналі

ee clientfifo.c на другому терміналі

Для збереження треба натиснути Esc + Enter.

4 Відкомпілюйте програми:

cc -o serverfifo serverfifo.c

cc -o clientfifo clientfifo.c

5 У разі успішної компілювання на першому терміналі командою ls -1 можна спостерігати з’явлення виконуваного файла ./serverfifo, а на другому — ./clientfifo.

6 Перевірте результати роботи програм; у разі з’явлення повідомлень про помилки, поясніть їх та усуньте, після чого знову запустіть програми та отримайте позитивний результат — з’явлення на терміналі сервера Ваших прізвища, ім’я та по-батькові.

7 Змоделюйте ситуації, коли неможливо створити, відкрити та вилучити FIFO, а також коли виникає помилка виведення та записування, потім знову налаштуйте програми та виконайте їх.


^ 6 Зміст протоколу


Протокол лабораторної роботи “Взаємодія процесів в ОС UNIX за допомогою іменованих каналів” оформлюється в робочому зошиті в послідовності, котра визначається стандартом підприємства з основ лабораторного практикуму. Протокол має містити назву лабораторної роботи та її мету, результати виконання домашнього завдання згідно з вимогами розділу 4; тексти програм serverfifo та clientfifo з коментарями; результати виконання пунктів 1...7 лабораторного завдання з коментарями.


7 Список рекомендованої літератури


1 Робачевский А. М. Операционная система UNIX. — СПб.: БХВ-Петербург, 2002.

2 Ивановский С. Операционная система UNIX. — М.: Познавательная книга плюс, 2000.

3 Дегтярев Е. К. Введение в UNIX. — М.: МП "Память", 1991.

4 http://www.freebsd.org.ru


Лабораторна робота № 16

^ ВЗАЄМОДІЯ ПРОЦЕСІВ В ОС UNIX ЗА ДОПОМОГОЮ ІНТЕРФЕЙСУ СОКЕТІВ

1 Мета роботи


Метою роботи є ознайомлення з програмними засобами створення комунікаційних вузлів та організація обміну даними за допомогою сокетів.


^ 2 Основні положення


2.1 Загальні вимоги до міжпроцесної взаємодії


Взаємодія поміж процесами має бути уніфікованою, незалежно від того, виконуються ці процеси на одному чи то на різних комп’ютерах у мережі. Комунікаційні характеристики взаємодії мають бути доступними для процесів в уніфікованій формі, тобто додаток може вимагати конкретного виду зв’язку, який грунтуватиметься на віртуальному каналі, дейтаграмах тощо. Будь-який спосіб взаємодії має забезпечувати такі сервіси:

впорядковане доставлення даних;

відсутність дублювання даних;

надійне доставлення даних;

підтримку передавання екстрених даних;

попереднє встановлення зв’язку.

Канали забезпечують лише три перші характеристики; дані мають вигляд потоку, виокремлення з нього за необхідності окремих повідомлень має забезпечуватися додатками, які можуть взаємодіяти.

Усім наведеним вимогам задовольняють спеціальні об’єкти — сокети (socket). Сокети створюються у межах певного комунікаційного домена (communication domain), який описує набір характеристик взаємодії. Сокет означає поняття комунікаційного вузла, який забезпечує приймання та передавання даних для процесу. Адресування сокетів, їхнє розташування, протоколи передавання даних можуть бути різними. Це описується в понятті комунікаційного домена. Сокети мають інтерфейс доступу до файлової системи UNIX та можуть бути адресовані цілим числом — дескриптором. На відміну від звичайних файлів, сокети — це віртуальний об’єкт, який існує доти, поки на нього посилається хоча б один з процесів.

Взаємодія з попереднім установленням з’єднання передбачає створення віртуального каналу поміж джерелом та одержувачем даних. Це позбавляє від необхідності ідентифікувати передавальну сторону у кожному пакеті даних. Ідентифікування відбувається на початковому етапі встановлення зв’язку, а потім зберігається для усіх пакетів, які належать даному віртуальному каналові.

І, врешті, передавання екстрених повідомлень передбачає їхнє доставляння поза нормальним потоком. Зазвичай ці повідомлення пов’язано з певними терміновими подіями, які потребують негайного реагування.

У BSD UNIX зреалізовані такі основні типи сокетів:

сокет дейтаграм (Datagram Socket), через який здійснюється теоретично ненадійне, незв’язане передавання пакетів;

сокет потоку (Stream Socket), через який здійснюється передавання потоку даних без зберігання меж повідомлень. Цей тип сокетів підтримує передавання екстрених повідомлень;

сокет пакетів (Packet Socket), через який здійснюється надійне передавання даних без дублювання з попереднім встановленням зв’язку. Межі повідомлень зберігаються;

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

Для того щоби незалежні процеси мали можливість взаємодіяти, для сокетів треба визначити простір імен. Ім’я сокета має сенс лише у рамцях комунікаційного домена, в якому його створено. Імена сокетів мають смисл адрес.


^ 2.2 Програмний інтерфейс сокетів


Сокет — це комунікаційний інтерфейс взаємодіючих процесів. Конкретний характер взаємодії залежить від типу використовуваних сокетів, а комунікаційний домен, у межах якого створено цей сокет, визначає базові властивості цієї взаємодії. Нижче наведені типи сокетів та їхні назви:

Сокет дейтаграм — SOCK_DGRAM

Сокет потоку — SOCK_STREAM

Сокет пакетів — SOCK_SEQPACKET

Сокет низького рівня — SOCK_RAW

Останній тип сокетів використовується для переглядання ICMP-повідомлень.

Для створення сокета процес має зазначити тип сокета та комунікаційний домен, у рамцях якого використовуватиметься сокет. Комунікаційний домен може підтримувати використання кількох протоколів, тому процес може зазначити конкретний комунікаційний протокол для взаємодії. Але якщо його не зазначено, система сама обирає найбільш придатний зі списку протоколів, доступних для даного комунікаційного домена. Для створення сокета використовується системний виклик socket(2):

#include

#include

int socket (int domain, int type, int protocol)

Аргумент domain визначає комунікаційний домен, type — тип сокета, а protocol — використовуваний протокол, за умовчанням зазначається непрямо і може дорівнювати 0. У разі успішного виконання системний виклик повертає додатне ціле число, аналогічне файловому дескриптору, яке трактується далі як адреса даного сокета у подальших викликах.

Комунікаційний домен визначає сім’ю протоколів (Protocol Family), припустимих у межах даного домена. Можливі значення аргументу domain такі:

AF_UNIX — домен локальної міжпроцесної взаємодії у межах однієї ОС UNIX, внутрішні протоколи.

AF_INET — домен взаємодії процесів віддалених систем, протокол Internet (TCP/IP).

AF_NS — домен взаємодії процесів віддалених систем, протокол

Хerox NS.

Префікс AF визначає адресний простір взаємодії; припустимі є також назви з префіксом PF (Protocol Family); PF_UNIX, PF_INET тощо. Для домена AF_INET можливі такі комбінації типу сокета та використовуваного комунікаційного протоколу:

^ SOCK_STREAM IPPROTO_TCP (TCP)

SOCK_DGRAM IPPROTO_UDP (UDP)

SOCK_RAW IPPROTO_ICMP (ICMP)

SOCK_ RAW IPPROTO_RAW (IP)

Для однозначної ідентифікації сокета його слід прив’язати до простору імен конкретного комунікаційного домена. Кожний комунікаційний канал визначається двома вузлами — джерелом та отримувачем даних і схарактеризовується п’ятьма параметрами:

комунікаційним протоколом,

локальною адресою,

локальним процесом,

віддаленою адресою,

віддаленим процесом.

Адреса визначає операційну систему (чи хост мережі), а процес — конкретний додаток, який передає чи то отримує дані. Конкретні ж значення й формат цих параметрів визначаються комунікаційним доменом. При створенні сокета вказується лише один параметр — комунікаційний протокол, тому, перш ніж передавати або приймати дані, треба зазначити ще чотири параметри для комунікаційного каналу. Взаємодіючі процеси мають робити це узгоджено, використовуючи заздалегідь визначені адреси, або домовляючись щодо них у перебігу встановлення зв’язку. Процедура встановлювання цих параметрів істотно залежить від типу створюваного каналу, який визначається типом сокета та комунікаційного протоколу.

На рис. 2.1 подано взаємодію поміж процесами при віртуальному комунікаційному каналі з попереднім встановленням зв’язку.





Рисунок 2.1 — Взаємодія поміж процесами при створюванні віртуального каналу з попереднім встановленням зв’язку


На рис. 2.2 подано взаємодію, базовану на дейтаграмах без попереднього встановлення зв’язку.





Рисунок 2.2 — Взаємодія поміж процесами, базована на дейтаграмах

без попереднього встановлення зв’язку


Фактичному передаванню даних передує первісна фаза зв’язування (Binding) сокета засобами встановлення додаткової інформації, необхідної для визначення комунікаційного вузла. Зв’язування зреалізовується за допомогою системного виклику bind(2):

#include

#include

int bind (int sockfd, struct sockaddr *localaddr, int addrlen).

Дескриптор сокета, sockfd, отримується при створюванні сокета; аргумент localaddr визначає локальну адресу, з якою треба зв’язати сокет; параметр addrlen визначає розмір адреси. У процедурі зазначається локальна адреса, яка визначає два параметри комунікаційного каналу: локальну адресу та локальний процес.


Адреса сокета залежить від комунікаційного домена, в межах якого його визначено. У титульному файлі адреса визначається у такий спосіб:

struckt sockaddr {

u_short sa_family;

char sa_data[14];

};

Поле sa_family визначає комунікаційний домен (сім’ю протоколів), а sa_data вміщує саме адресу, формат якої визначено для кожного домена. Наприклад, для внутрішнього домена UNIX адреса, визначена y , має вигляд

struckt sockaddr_un {

short sun_family; /*= = AF_UNIX*/;

char sun_path[108];

};

У цьому разі взаємодіючі процеси виконуються під керуванням однієї ОС на одному хості, комунікаційний вузол може бути однозначно визначено лише одним параметром — локальним процесом. У домені UNIX за адресу вважається ім’я файла.




Рисунок 2.3 — Адреси сокетів


У разі мережного обміну даними слід зазначити адресу як локального процесу, так і хоста, на якому виконується даний процес. Для домена Internet (сім’я протоколів ТСР/ІР) використовується формат адрес, визначений у файлі :

struct sockaddr_in {

short sin_family; /*= = AF_INET */;

u_short sin_port;

struckt in_addr sin_addr;

char sin_zero[8];

};

Адреса цього домена (ІР-адреса) — це 32-розрядне ціле число sin_addr, а процес-додаток адресується 16-розрядним номером порту sin_port (рис. 2.3).

Зв’язування потрібне для привласнення сокетові локальної адреси й тим самим визначення комунікаційного вузла і зреалізовується системною функцією bind(2):

Сервер реєструє свою адресу, яка має бути відома заздалегідь клієнтам, які “спілкуються” з сервером. Зв’язування необхідне перш ніж сервер буде готовий до приймання запитів від клієнтів.

За взаємодії без попереднього встановлення зв’язку та створення віртуального каналу клієнт також повинен заздалегідь зареєструвати свою адресу, яка є унікальною в межах комунікаційного домена. У разі домена UNIX цим опікується додаток. Ця адреса не повинна бути відома серверові, тому що запит завжди ініціює клієнт і автоматично передає разом з ним власну адресу. Отримана адреса віддаленого вузла використовується сервером для мультиплексування повідомлень, які надсилаються різним клієнтам.

У разі взаємодії з використанням віртуального каналу клієнт може зареєструвати власну адресу й не спрямовувати цю функцію системі.

Призначення адреси для клієнта можна виконувати за допомогою системного виклику connect(2), який встановлює зв’язок з сервером і автоматично зв’язує сокет клієнта з локальним комунікаційним вузлом. Виклик connect(2) має вигляд

#include

#include

int connect (int sockfd, struct sockaddr *servaddr, int addrlen);

Системний виклик connect(2) створює віртуальний канал та виконується для попереднього встановлення зв’язку між комунікаційними вузлами. Клієнтові не треба зв’язувати сокет за допомогою системного виклику bind(2). Локальний вузол комунікаційного каналу зазначається дескриптором сокета sockfd, для якого система автоматично обирає потрібні значення локальної адреси та процесу. Віддалений вузол визначається аргументом servaddr, який вказує на адресу серверові, а addrlen задає його довжину.

Виклик connect(2) може також використовуватися і клієнтами, які створюють сокети дейтаграм без створення віртуального каналу. У такому разі connect(2) не зреалізовує фактичного з’єднання з сервером, а може бути використаний для зберігання параметрів адреси сервера, якому буде спрямовано дейтаграми. Клієнт буде позбавлений від необхідності зазначати адресу серверові при кожному відправленні даних.

Системний виклик listen(2) інформує систему про готовність сервера приймати запитання. Він має такі параметри:

#include

#include

int listen (int sockfd, int backlog);

Параметр backlog зазначає максимально можливу кількість запитань на встановлення зв’язку, які можуть очікувати, коли їх опрацює сервер. Якщо запит надходить, коли черга очікуючих запитів є повна, виклик connect(2) клієнта завершиться для домена UNIX (AF_UNIX) з помилкою ECONNRЕFUSED. Для інших доменів результат буде залежати від того, чи підтримує протокол повторне передавання запиту. Протокол ТСР (домен AF_INET) передаватиме повторні запити, допоки кількість запитів у черзі не зменшиться або не настане тайм-аут, окреслений для протоколу. У цьому разі виклик клієнта завершиться з помилкою ETIMEDOUT.

Фактичне опрацювання запиту клієнта на встановлення зв’язку зреалізовує системний виклик accept(2):

#include

#include

int accept (int sockfd, struct sockaddr *clntaddr, *int addrlen);

Виклик accept(2) обирає перший запит з черги і створює новий сокет, характеристики якого не відрізняються від сокета sockfd і завершує створення віртуального каналу з боку сервера. Одночасно accept(2) повертає параметри віддаленого комунікаційного вузла — адресу клієнта clntaddr та його розмір addrlen. Новий сокет використовується для обслуговування створеного віртуального каналу, а отримана ним адреса клієнта виключає його анонімність. Типовий сценарій взаємодії має вигляд:

sockfd = socket(...); Створити сокет

bind (sockfd, …); Сполучити його з відомою локальною адресою

listen (sockfd, …); Організувати чергу запитів

for ( ; ; ) {

newsockfd = accept (sockfd, …) ; Отримати адресу

if /fork( ) = = 0 { ; Породити дочірній процес

close (sockfd) ; Дочірній процес

·

·

·

exit (0);

}

else

close (newsockfd); Батьківський процес

}


У цьому сценарії, у той час, коли дочірній процес забезпечує фактичний обмін даними з клієнтом, батьківський процес продовжує “прослуховувати” запити, котрі знову надходять, породжуючи для кожного з них окремий процес-опрацьовувач. Черга дозволяє буферизувати запити на той час, коли сервер завершує виклик accept(2), а потім створює дочірній процес. Новий сокет newsockfd, який створюється викликом accept(2), адресує повністю визначений комунікаційний канал: протокол та повні адреси обох вузлів — клієнта та сервера. Для сокета sockfd визначено лише локальну частину каналу. Це дозволяє серверові продовжувати використання sockfd для “прослуховування” наступних запитів.

Системні виклики listen(2) та accept(2) використовуються сервером лише в разі встановлення віртуального каналу поміж сервером та клієнтом.

Якщо для сокетів потоку під час приймання та передавання даних можуть використовуватися стандартні виклики read(2) та write(2), то сокети дейтаграм мають користуватися спеціальними системними викликами, які також є доступними для інших типів сокетів.

#include

#include

int send (int s, const char *msg, int len, int flags);

int sendto (int s, const char *msg, int len, int flags,

const struct sockaddr *toaddr, int tolen);

int recv (int s, char *buf, int len, int flags);

int rеcvfrom (int s, char *buf, int len, int flags,

struct sockaddr *fromaddr, int * fromlen)

Функції send(2) та sendto(2) використовуються для передавання даних віддаленому вузлу, а функції recv(2) та rеcvfrom(2) — для їхнього приймання. Основною відміною поміж ними є те, що функції send(2) та recv(2) використовуються лише для “долученого” сокета, тобто після виклику connect(2).

Усі ці виклики використовують перший аргумент — дескриптор сокета, через який зреалізовується обмін даними. Аргумент msg вміщує повідомлення довжиною len, яке передається за адресою toaddr, довжина його становить tolen байтів. Для функції send(2) використовується адреса одержувача, встановлена попереднім викликом connect(2). Аргумент buf — це буфер, у який копіюються отримані дані.

Параметр flags може набирати таких значень:

MSG_OOB Передати або прийняти екстрені дані (out of band) замість звичайних

MSG_PEEK Переглянути дані без вилучення їх з системного буфера (наступні операції читання отримають ті ж самі дані)


^ 2.3 Приклад використання сокета


Взаємодію поміж процесами за допомогою сокетів можна продемонструвати на прикладі домена UNIX. Функціональність розподіленої системи у цьому разі полягає в тому, що клієнт надсилає серверові повідомлення, сервер переспрямовує його клієнтові, який і виводить його після отримання на термінал, оскільки у домені UNIX сокети дейтаграм практично не відрізняються від сокетів потоку. Як адресу сервера можна зазначити ім’я файла ./echo.server й припустити, що
еще рефераты
Еще работы по разное