- •Практична робота 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()
Функції перетворення ip-адрес inet_ntoa(), inet_aton()
Нам також знадобляться функції, що здійснюють переклад IP-адрес з символьного уявлення (у вигляді четвірки чисел, розділених крапками) в числове уявлення і назад. Функція inet_aton() переводить символьну IP-адресу в числове уявлення в мережному порядку байт.
Функція повертає 1, якщо в символьному вигляді записана правильна IP-адреса, і 0 інакше – для більшості системних викликів і функцій це нетипова ситуація. Зверніть увагу на використовування покажчика на структуру struct in_addr як один з параметрів даної функції. Ця структура використовується для зберігання IP-адрес в мережному порядку байт. Те, що використовується структура, що складається з однієї змінної, а не сама 32-бітова змінна, склалося історично, і автори в цьому не винуваті.
Для зворотного перетворення застосовується функція inet_ntoa().
Функції перетворення IP-адрес
Прототипи функцій
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int inet_aton(const char *strptr
struct in_addr *addrptr);
char *inet_ntoa(struct in_addr *addrptr);
Опис функцій
Функція inet_aton переводить символьну IP-адресу, розташовану по покажчику strptr, в числове уявлення в мережному порядку байт і заносить його в структуру, розташовану за адресою addrptr. Функція повертає значення 1, якщо в рядку записана правильна IP-адреса, і значення 0 інакше. Структура типу struct in_addr використовується для зберігання IP-адрес в мережному порядку байт і виглядає так:
struct in_addr {
in_addr_t s_addr;
};
Те, що використовується адреса такої структури, а не просто адреса змінної типу in_addr_t, склалося історично.
Функція inet_ntoa застосовується для зворотного перетворення. Числове представлення адреси в мережному порядку байт повинне бути занесено в структуру типу struct in_addr, адреса якої addrptr передається функції як аргумент. Функція повертає покажчик на рядок, що містить символьне представлення адреси. Цей рядок розташовується в статичному буфері, при подальших викликах її новий вміст замінює старий вміст.
Функція bzero()
Функція 2 настільки проста, що про неї нічого розказувати. Все видно з опису.
Функція bzero
Прототип функції
#include <string.h>
void bzero(void *addr, int n);
Опис функції
Функція Функція bzero заповнює перші n байт, починаючи з адресою addr, нульовими значеннями. Функція нічого не повертає.
Тепер ми можемо перейти до системних викликів, створюючих інтерфейс між призначеним для користувача рівнем стека протоколів TCP/IP і транспортним протоколом UDP.
Створення сокета. Системний виклик socket()
Для створення сокета в операційній системі служить системний виклик socket(). Для транспортних протоколів сімейства TCP/IP існує два види сокетів: UDP-сокет – сокет для роботи з датаграммами, і TCP сокет – потоковий сокет. Проте поняття сокета (див. лекцію 14, роздягнув "Повні адреси. Поняття сокета (socket)") не обмежується рамками тільки цього сімейства протоколів. Даний інтерфейс мережних системних викликів (socket(), bind(), recvfrom(), sendto() і т. д.) в операційній системі UNIX може застосовуватися і для інших стеків протоколів (і для протоколів, що лежать нижче за транспортний рівень).
При створенні сокета необхідно точно специфікувати його тип. Ця специфікація проводиться за допомогою трьох параметрів виклику socket(). Перший параметр указує, до якого сімейства протоколів відноситься створюваний сокет, а другий і третій параметри визначають конкретний протокол всередині даного сімейства.
Другий параметр служить для завдання виду інтерфейсу роботи з сокетом – буде це потоковий сокет, сокет для роботи з датаграммами або який-небудь інший. Третій параметр указує протокол для заданого типу інтерфейсу. В стеку протоколів TCP/IP існує тільки один протокол для потокових сокетів – TCP і лише один протокол для датаграммных сокетів – UDP, тому для транспортних протоколів TCP/IP третій параметр ігнорується.
В інших стеках протоколів може бути декілька протоколів з однаковим видом інтерфейсу, наприклад, датаграммных, що розрізняються по ступеню надійності.
Для транспортних протоколів TCP/IP ми завжди як перший параметр указуватимемо приречену константу AF_INET (Address family – Internet) або її синонім PF_INET (Protocol family – Internet).
Другий параметр прийматиме приречені значення SOCK_STREAM для потокових сокетів і SOCK_DGRAM – для датаграммных.
Оскільки третій параметр в нашому випадку не враховується, в нього ми підставлятимемо значення 0.
Посилання на інформацію про створений сокет поміщається в таблицю відкритих файлів процесу подібно тому, як це робилося для pip’ов і FIFO (див. семінар 5). Системний виклик повертає користувачу файловий дескриптор, відповідний заповненому елементу таблиці, який далі ми називатимемо дескриптором сокета. Такий спосіб зберігання інформації про сокет дозволяє, по-перше, процесам-дітям успадковувати її від процесів-батьків, а, по-друге, використовувати для сокетів частину системних викликів, які вже знайомі нам по роботі з pip’ами і FIFO: close(), read(), write().
Системний виклик для створення сокета
Прототип системного виклику
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type
int protocol);
Опис системного виклику
Системний виклик socket служить для створення віртуального комунікаційного вузла в операційній системі. Даний опис не є повним описом системного виклику, а призначено тільки для використовування в нашому курсі. За повною інформацією звертайтеся до UNIX Manual.
Параметр domain визначає сімейство протоколів, в рамках якого здійснюватиметься передача інформації. Ми розглянемо тільки два такі сімейства з декількох існуючих. Для них є приречені значення параметра:
PF_INET – для сімейства протоколів TCP/IP;
PF_UNIX – для сімейства внутрішніх протоколів UNIX, інакше званого ще UNIX domain.
Параметр type визначає семантику обміну інформацією: чи здійснюватиметься зв'язок через повідомлення (datagrams), за допомогою встановлення віртуального з'єднання або ще яким-небудь чином. Ми користуватимемося тільки двома способами обміну інформацією з приреченими значеннями для параметра type:
SOCK_STREAM – для зв'язку за допомогою встановлення віртуального з'єднання;
SOCK_DGRAM – для обміну інформацією через повідомлення.
Параметр protocol специфікує конкретний протокол для вибраного сімейства протоколів і способу обміну інформацією. Він має значення тільки у тому випадку, коли таких протоколів існує дещо. В нашому випадку сімейство протоколів і тип обміну інформацією визначають протокол однозначно. Тому даний параметр ми вважатимемо рівним 0.
Значення, що повертається
У разі успішного завершення системний виклик повертає файловий дескриптор (значення більше або рівне 0), який використовуватиметься як посилання на створений комунікаційний вузол при всіх подальших мережних викликах. При виникненні якої-небудь помилки повертається негативне значення.
