Організація зв'язку між видаленими процесами за допомогою датаграм
Як вже згадувалося в лекціях, більш простою для взаємодії видалених процесів є схема організації спілкування клієнта і серверу за допомогою датаграм, тобто використовування протоколу UDP. Розгляд цієї схеми ми почнемо з деякої житейської аналогії, а потім переконаємося, що кожній життєво обґрунтованій дії в операційній системі UNIX відповідає певний системний виклик. З погляду звичайної людини спілкування процесів за допомогою датаграм нагадує спілкування людей в листах. Кожний лист є закінченим повідомленням, що містить адресу одержувача, адресою відправника і вказівками, хто написав лист і хто повинен його одержати. Листи можуть втрачатися, доставлятися в неправильному порядку, бути пошкодженими в дорозі і т.д. Що в першу чергу повинна зробити людина, що проживає у віддаленій місцевості, для того, щоб приймати і відправляти листи? Він повинен виготовити поштовий ящик, який одночасно служити і для прийому кореспонденції, і для її відправки. Листи, що прийшли, листоноша поміщатиме в цей ящик і забиратиме з нього листи, підготовлені до відправки. Виготовлений поштовий ящик потрібно десь прикріпити. Це можуть бути парадні двері будинку або вхід з двору, огорожа, стовп, дерево і т.п. Потенційно може бути виготовлено декілька поштових ящиків і розміщено в різних місцях з тим, щоб листи від різних адресатів прибували в різні ящики. Цим ящикам відповідатимуть різні адреси: "г. Іванову, поштовий ящик на стайні", "г. Іванову, поштовий ящик, що на дубі". Після закріплення ящика ми готові до обміну кореспонденцією. Людина-клієнт пише лист із запитом за наперед відомою йому адресою людини-серверу і чекає отримання у відповідь листа. Після отримання відповіді він читає його і переробляє одержану інформацію. Людина-сервер спочатку знаходиться в стані очікування запиту. Одержавши лист, він читає текст запиту і визначає адресу відправника. Після обробки запиту він пише відповідь і відправляє його за зворотною адресою, після чого починає чекати наступного запиту. Всі ці модельні дії мають аналоги при спілкуванні видалених процесів по протоколу UDP. Процес-сервер повинен спочатку вчинити підготовчі дії: створити UDP-сокет (виготовити поштовий ящик) і пов'язати його з певним номером порту і IP-адресою мережного інтерфейсу (прикріпити поштовий ящик у визначеному місці) – набудувати адресу сокета. При цьому сокет може бути прив'язаний до конкретного мережного інтерфейсу (до стайні, до дуба) або до комп'ютера в цілому, тобто в повній адресі сокета може бути або вказана IP-адреса конкретного мережного інтерфейсу, або дано вказівку операційній системі, що інформація може поступити через будь-який мережний інтерфейс, що є в наявності. Після настройки адреси сокета операційна система починає приймати повідомлення, що прийшли на цю адресу і складати їх в сокет. Сервер чекає надходження повідомлення, читає його, визначає, від кого воно поступило і через який мережний інтерфейс, обробляє одержану інформацію і відправляє результат за зворотною адресою. Після чого процес готовий до прийому нової інформації від того ж або іншого клієнта. Процес-клієнт повинен спочатку вчинити ті ж самі підготовчі дії: створити сокет і набудувати його адресу. Потім він передає повідомлення, вказавши, кому воно призначено (IP-адреса мережного інтерфейсу і номер порту серверу), чекає від нього відповіді і продовжує свою діяльність. Схемно ці дії виглядають так, як показано на рисунке 15–16.6. Кожному з них відповідає певний системний виклик. Назви викликів написані праворуч від блоків відповідних дій. Створення сокета проводиться за допомогою системного виклику socket(). Для прив'язки створеного сокета до IP-адреси і номера порту (настройка адреси) служить системний виклик bind(). Очікуванню отримання інформації, її читанню і, при необхідності, визначенню адреси відправника відповідає системний виклик recvfrom(). За відправку датаграммы відповідає системний виклик sendto(). Перш ніж приступити до докладного розгляду цих системних викликів і прикладів програм нам доведеться зупинитися на декількох допоміжних функціях, які ми повинні будуть використовувати при програмуванні. Мережний порядок байт. Функції htons(), htonl(), ntohs(), ntohl() Передача від одного обчислювального комплексу до іншого символьної інформації, як правило (коли один символ займає один байт), не викликає проблем. Проте для числової інформації ситуація ускладнюється. Мал. 15-16.6. Схема взаємодії клієнта і серверу для протоколу UDP Як відомо, порядок байт в цілих числах, представлення яких займає більше одного байта, може бути для різних комп'ютерів неоднаковим. Є обчислювальні системи, в яких старший байт числа має меншу адресу, ніж молодший байт (big-endian byte order), а є обчислювальні системи, в яких старший байт числа має більшу адресу, ніж молодший байт (little-endian byte order). При передачі цілої числової інформації від машини, що має один порядок байт, до машини з іншим порядком байт ми можемо неправильно тлумачити прийняту інформацію. Для того, щоб цього не відбулося, було введено поняття мережного порядку байт, тобто порядку байт, в якому повинна представлятися ціла числова інформація в процесі передачі її по мережі (насправді – це big-endian byte order). Цілі числові дані з уявлення, прийнятого на комп'ютері-відправнику, переводяться призначеним для користувача процесом в мережний порядок байт, у такому вигляді подорожують по мережі і переводяться в потрібний порядок байт на машині-одержувачі процесом, якому вони призначені. Для перекладу цілих чисел з машинного уявлення в мережне і назад використовується чотири функції: htons(), htonl(), ntohs(), ntohl().
|