Skip to content

Latest commit

 

History

History
121 lines (82 loc) · 6.83 KB

File metadata and controls

121 lines (82 loc) · 6.83 KB

Системные вызовы

Системные вызовы для работы с сетью, отдают ядру ОС всю часть грязной работы, давая нам только высокоуровневые операции для работы.

Самое важное, при работе с системными вызовами - это порядок вызова и обработка ошибок.

Так как работа сети немыслима без внутренних функций ядра ОС, мы вынуждены использовать системные вызовы для работы с сетью.

В этой статье мы разберем порядок системных вызовов и сигнаруты их функций. Для краткости, обработка ошибок делаться не будет. Однако, при работе с системными вызовами, обработка ошибок - обязательна.

Большинство системных вызовов возращают определенное целочисленное значение, сигнализирующее об успешности иили сбое, например, при сболе - -1 (но не все!). Далее, нужно обработать ситуацию ошибки, обернув ее в if:

int syscall_res = some_sys_call();
if ( syscall_res == -1 ) {
  // ваша обработка ошибок.
  perror("some_sys_call failed.");
  exit(1);
}

Получить сообщение об конкретной ошибке, можно с помощью переменной errno, или вывести ее простым вызовом perror() из <stdio.h>.

getaddrinfo()

Эта функция одна из самых необходимых, она позволяет настроить структуры, которыми вы будете пользоваться в дальнейшем. Имеет множество опций, но ее использование, на самом деле, довольно простое.

getaddrinfo() делает следующее:

  • избавляет вас, от конкретной версии IP-протокола (IPv4 или IPv6), работает с обеими, автоматически.
  • может проводить DNS-поиск имени хоста (если вместо адреса, передадите имя хоста, например example.com)
  • заполняет необходимые структуры
int getaddrinfo(
    const char* node, // 'example.com' или IP-адрес
    const char* service, // например, http, или номер порта
    const struct addrinfo* hints, 
    struct addrinfo** res
);

Вы даете этой функции три вводных параметра, а она вам возвращает связный список результатов res.

Параметры функции:

  1. const char* node - это может быть имя хоста example.com, или IP-адрес 41.152.322.22.

  2. const char* service - можно передать номер порта "8080" или ключ конкретной службы - http, ftp, telnet, что угодно.

  3. const struct addrinfo* hints - заранее заполненная информация с настройками.

Простой пример использования getaddrinfo(), если вы хотите сделать сервер, который прослушивает на вашем IP-адресе и порте 3490:

int status;
struct addrinfo hints;
struct addrinfo* servinfo; // результаты getaddrinfo()

memset(&hints, 0, sizeof(hints)); // обнуление структуры параметров (обязательно)

// заполнение параметров
hints.ai_family = AF_UNSPEC; // без разницы IPv4 или IPv6
hints.ai_socktype = SOCK_STREAM; // TCP 
hints.ai_flags = AI_PASSIVE; // заполнение моего IP за меня

if( ( satus = getaddrinfo( NULL,"3490",&hints,&servinfo ) ) != 0 ) {
    fprintf(stderr, "gai error: %s\n", gai_strerror(status));
    exit(1);
}

// servinfo сейчас указывает на связный список struct addrinfo размером 1 или более

//... делается что угодно, пока требуется servinfo

freeaddrinfo(servinfo); // освобождение связного списка

Для получения строки ошибки из функции getaddrinfo() используется специальная функция gai_strerror(status), кудае передается возвращаемое значение из getaddrinfo().

Связный список struct addrinfo* servinfo далее можно использовать: для перебора его элементов, получения из кажого этого элемента struct sockaddr для наших нужд.

А вот пример использования getaddrinfo() со стороны клиента, который хочет подключиться к хосту www.example.net на порте 3490:

int status;
struct addrinfo hints;
struct addrinfo *servinfo;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

status = getaddrinfo("www.example.net", "3490", &hints, &servinfo);

// и так далее.

Простая программа для вывода IP адреса хоста

show_ip.c - ссылка.

Эта программа получает аргументом командной строки имя хоста, и выводит все его IP-адреса в терминал. В ней используется функция getaddrinfo(), которая создает связный список адресов хоста.

Пример вывода:

$ ./show-ip yandex.ru
IP addresses for yandex.ru:

    IPv4: 5.255.255.77
    IPv4: 77.88.55.88
    IPv4: 77.88.44.55
    IPv6: 2a02:6b8:a::a

./show-ip goodgame.ru
IP addresses for goodgame.ru:

    IPv4: 127.0.0.1

Итог работы getaddrinfo()

Теперь, имея результат работы функции getaddrinfo(), а именно связный список, правильно настроенных адресов, мы можем приступить к дальнейшим системным вызовам для сетевых операций, которым нужны эти адреса.