- •Практична робота 10
- •Загальні відомості про архітектуру сімейства протоколів tcp/ip
- •Рівень мережного інтерфейсу
- •Рівень Internet. Протоколи ip, icmp, arp, rarp. Internet–адреси
- •Транспортний рівень. Протоколи tcp і udp. Tcp і udp сокети. Адресні простори портів. Поняття encapsulation
- •Рівень додатків/процесів
- •Використовування моделі клієнт-сервер для взаємодії видалених процесів
- •Організація зв'язку між видаленими процесами за допомогою датаграм
- •Мережний порядок байт. Функції htons(), htonl(), ntohs(), ntohl()
- •Функції перетворення ip-адрес inet_ntoa(), inet_aton()
- •Функція bzero()
- •Створення сокета. Системний виклик socket()
- •Адреси сокетів. Настройка адреси сокета. Системний виклик bind()
Рівень додатків/процесів
До цього рівня можна віднести протоколи TFTP (Trivial File Transfer Protocol), FTP (File Transfer Protocol), telnet, SMTP (Simple Mail Transfer Protocol) і інші, які підтримуються відповідними системними утилітами. Про їх використовування детально розказано в UNIX Manual, і зупинятися на них ми не будемо.
Нас цікавитиме надалі програмний інтерфейс між рівнем додатків/процесів і транспортним рівнем для того, щоб ми могли створювати власні процеси, що спілкуються через мережу. Але перш ніж зайнятися програмним інтерфейсом, нам необхідно пригадати особливості взаємодії процесів в моделі клієнт-сервер.
Використовування моделі клієнт-сервер для взаємодії видалених процесів
В матеріалах семінару 9 при обговоренні мультиплексування повідомлень (роздягнув "Поняття мультиплексування. Мультиплексування повідомлень. Модель взаємодії процесів клієнт-сервер. Нерівноправність клієнта і серверу") мовилося про використовування моделі клієнт-сервер для організації взаємодії локальних процесів. Ця ж модель, спочатку припускаюча нерівноправність взаємодіючих процесів, найбільш часто використовується для організації мережних додатків. Нагадаємо основні відмінності процесів клієнта і серверу стосовно видаленої взаємодії:
Сервер, як правило, працює постійно, на всьому протязі життя додатку, а клієнти можуть працювати епізодично.
Сервер чекає запиту від клієнтів, ініціатором же взаємодії виступає клієнт.
Як правило, клієнт звертається до одного серверу за раз, тоді як до серверу можуть одночасно поступити запити від декількох клієнтів.
Клієнт повинен знати повну адресу серверу (його локальну і видалену частині) перед початком організації запиту (до початку спілкування), тоді як сервер може одержати інформацію про повну адресу клієнта із запиту, що прийшов (після початку спілкування).
І клієнт, і сервер повинні використовувати один і той же протокол транспортного рівня.
Нерівноправність процесів в моделі клієнт-сервер, як ми побачимо далі, накладає свій відбиток на програмний інтерфейс, що використовується між рівнем додатків/процесів і транспортним рівнем.
Поступаючі запити сервер може обробляти послідовно – запит за запитом – або паралель, запускаючи для обробки кожного з них свій процес або thread. Як правило, сервери, орієнтовані на зв'язок клієнт-сервер за допомогою установки логічного з'єднання (TCP-протокол), ведуть обробку запитів паралельно, а сервери, орієнтовані на зв'язок клієнт-сервер без встановлення з'єднання (UDP-протокол), обробляють запити послідовно.
Розглянемо основні дії, які нам необхідні в термінах абстракції socket для того, щоб організувати взаємодію між клієнтом і сервером, використовуючи транспортні протоколи стека TCP/IP.
Організація зв'язку між видаленими процесами за допомогою датаграм
Як вже згадувалося в лекціях, більш простою для взаємодії видалених процесів є схема організації спілкування клієнта і серверу за допомогою датаграм, тобто використовування протоколу UDP.
Розгляд цієї схеми ми почнемо з деякої житейської аналогії, а потім переконаємося, що кожній життєво обґрунтованій дії в операційній системі UNIX відповідає певний системний виклик.
З погляду звичайної людини спілкування процесів за допомогою датаграм нагадує спілкування людей в листах. Кожний лист є закінченим повідомленням, що містить адресу одержувача, адресою відправника і вказівками, хто написав лист і хто повинен його одержати. Листи можуть втрачатися, доставлятися в неправильному порядку, бути пошкодженими в дорозі і т.д.
Що в першу чергу повинна зробити людина, що проживає у віддаленій місцевості, для того, щоб приймати і відправляти листи? Він повинен виготовити поштовий ящик, який одночасно служити і для прийому кореспонденції, і для її відправки. Листи, що прийшли, листоноша поміщатиме в цей ящик і забиратиме з нього листи, підготовлені до відправки.
Виготовлений поштовий ящик потрібно десь прикріпити. Це можуть бути парадні двері будинку або вхід з двору, огорожа, стовп, дерево і т.п. Потенційно може бути виготовлено декілька поштових ящиків і розміщено в різних місцях з тим, щоб листи від різних адресатів прибували в різні ящики. Цим ящикам відповідатимуть різні адреси: "г. Іванову, поштовий ящик на стайні", "г. Іванову, поштовий ящик, що на дубі".
Після закріплення ящика ми готові до обміну кореспонденцією. Людина-клієнт пише лист із запитом за наперед відомою йому адресою людини-серверу і чекає отримання у відповідь листа. Після отримання відповіді він читає його і переробляє одержану інформацію.
Людина-сервер спочатку знаходиться в стані очікування запиту. Одержавши лист, він читає текст запиту і визначає адресу відправника. Після обробки запиту він пише відповідь і відправляє його за зворотною адресою, після чого починає чекати наступного запиту.
Всі ці модельні дії мають аналоги при спілкуванні видалених процесів по протоколу UDP.
Процес-сервер повинен спочатку вчинити підготовчі дії: створити UDP-сокет (виготовити поштовий ящик) і пов'язати його з певним номером порту і IP-адресою мережного інтерфейсу (прикріпити поштовий ящик у визначеному місці) – набудувати адресу сокета. При цьому сокет може бути прив'язаний до конкретного мережного інтерфейсу (до стайні, до дуба) або до комп'ютера в цілому, тобто в повній адресі сокета може бути або вказана IP-адреса конкретного мережного інтерфейсу, або дано вказівку операційній системі, що інформація може поступити через будь-який мережний інтерфейс, що є в наявності. Після настройки адреси сокета операційна система починає приймати повідомлення, що прийшли на цю адресу і складати їх в сокет. Сервер чекає надходження повідомлення, читає його, визначає, від кого воно поступило і через який мережний інтерфейс, обробляє одержану інформацію і відправляє результат за зворотною адресою. Після чого процес готовий до прийому нової інформації від того ж або іншого клієнта.
Процес-клієнт повинен спочатку вчинити ті ж самі підготовчі дії: створити сокет і набудувати його адресу. Потім він передає повідомлення, вказавши, кому воно призначено (IP-адреса мережного інтерфейсу і номер порту серверу), чекає від нього відповіді і продовжує свою діяльність.
Схемно ці дії виглядають так, як показано на рисунке 15–16.6. Кожному з них відповідає певний системний виклик. Назви викликів написані праворуч від блоків відповідних дій.
Створення сокета проводиться за допомогою системного виклику socket(). Для прив'язки створеного сокета до IP-адреси і номера порту (настройка адреси) служить системний виклик bind(). Очікуванню отримання інформації, її читанню і, при необхідності, визначенню адреси відправника відповідає системний виклик recvfrom(). За відправку датаграммы відповідає системний виклик sendto().
Перш ніж приступити до докладного розгляду цих системних викликів і прикладів програм нам доведеться зупинитися на декількох допоміжних функціях, які ми повинні будуть використовувати при програмуванні.
