Опубликован: 15.06.2004 | Доступ: свободный | Студентов: 2290 / 579 | Оценка: 4.35 / 3.96 | Длительность: 27:47:00
ISBN: 978-5-9556-0011-6
Лекция 14:

Заключение

< Лекция 13 || Лекция 14: 12345678910

Сетевые средства

Стандарт POSIX -2001 определяет сеть как совокупность взаимосвязанных хостов. Под сетевым адресом понимается видимый в пределах сети идентификатор, используемый для обозначения оконечных точек сети.

Процесс присвоения сетевого адреса оконечной точке называется связыванием, или привязкой, а обратное действие - освобождением , или отменой привязки.

Обычно оконечной точкой служит аппаратный сетевой интерфейс, посредством которого данные передаются и принимаются, однако с таким интерфейсом, как шлейфовый ( loopback ), никакой аппаратуры не ассоциировано.

Данные передаются по сети в виде последовательности октетов (восьмибитных беззнаковых величин). Если некоторый элемент данных (например, адрес или номер порта) состоит более чем из восьми бит, для его передачи и хранения требуется несколько октетов. Сетевым называется порядок октетов (байт), при котором первый (с наименьшим адресом) октет содержит старшие (наиболее значимые) биты.

При взаимодействии процессов оконечными точками служат сокеты, стандарт POSIX -2001 трактует их как отдельный тип файлов.

Под адресом сокета как (удаленной) оконечной точки понимается структура, включающая идентификатор адресного семейства и специфичную для данного семейства адресную информацию.

Адресное семейство соответствует определенной среде взаимодействия. Стандарт POSIX -2001 определяет три таких семейства: AF_UNIX ( межпроцессное взаимодействие в пределах одной системы), AF_INET (взаимодействие по протоколам IPv4 ), AF_INET6 (взаимодействие по протоколам IPv6 - необязательная возможность).

В пределах каждого адресного семейства могут существовать сокеты нескольких типов. Стандартом POSIX -2001 предусмотрено четыре типа: SOCK_STREAM (надежные, упорядоченные, полнодуплексные потоки октетов в режиме с установлением соединения), SOCK_SEQPACKET (аналог SOCK_STREAM с дополнительным сохранением границ между записями), SOCK_DGRAM (передача данных в виде датаграмм в режиме без установления соединения), SOCK_RAW (аналог SOCK_DGRAM с дополнительной возможностью доступа к протокольным заголовкам и другой информации нижнего уровня - необязательная возможность).

Для каждого адресного семейства каждый тип сокета может поддерживаться одним или несколькими протоколами. В частности, в адресном семействе AF_INET для сокетов типа SOCK_STREAM подразумеваемым является протокол с именем IPPROTO_TCP, а для типа SOCK_DGRAM - IPPROTO_UDP.

Общая логика работы с сокетами состоит в следующем. Сокеты создаются с помощью функции socket(), которой в качестве аргументов передаются адресное семейство, тип сокета и протокол, а в качестве результата получают открытый файловый дескриптор. Затем, посредством функции bind(), сокету присваивают локальный адрес. Если сокет ориентирован на режим с установлением соединения, то его следует пометить как готового принимать соединения, для чего понадобится функция listen(). Реальный прием соединений выполняет функция accept(), создающая для каждого из них новый сокет по образу и подобию "слушающего". В свою очередь, потенциальный партнер по взаимодействию инициирует соединение, прибегнув к функции connect(). (в режиме без установления соединения функция connect() позволяет специфицировать адрес отправляемых через сокет датаграмм.)

Для приема данных, поступивших в сокет, можно воспользоваться универсальной функцией низкоуровневого ввода/вывода read() или специализированным семейством функций recv*(), а для передачи - функцией write() или семейством send*(). Кроме того, посредством функций select() и/или poll() можно опросить наличие данных для приема или возможность отправки очередной порции данных.

Завершается взаимодействие между партнерами обращением к функции shutdown().

Данные о хостах как узлах сети хранятся в сетевой базе, последовательный доступ к которой обслуживается функциями sethostent(), gethostent() и endhostent().

Функция getaddrinfo() позволяет по имени узла сети ( хоста ) и/или имени сетевого сервиса получить набор адресов сокетов и ассоциированную информацию, что дает возможность создать сокет для обращения к заданному сервису.

Функция freeaddrinfo() носит технический характер: благодаря ей можно освободить память, зарезервированную функцией getaddrinfo().

Функцию getnameinfo() можно считать обратной по отношению к getaddrinfo(). Она позволяет по адресу сокета узнать имя узла и сервиса.

Техническую роль играют и функции преобразования ip-адресов из текстового представления в числовое и наоборот: inet_addr(), inet_ntoa(), inet_pton(), inet_ntop().

Первые две манипулируют только адресами IPv4: inet_addr() преобразует текстовую цепочку в целочисленное значение, пригодное для использования в качестве ip-адреса, inet_ntoa() выполняет обратное преобразование.

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

Для преобразования значений типов uint16_t и uint32_t из хостового порядка байт в сетевой служат функции htons() и htonl() ; функции ntohs() и ntohl() осуществляют обратную операцию.

Полезным дополнением к функциям getaddrinfo() и getnameinfo() является функция gai_strerror(), возвращающая текстовую цепочку, которая расшифровывает коды ошибок, перечисленные в заголовочном файле <netdb.h>.

Наряду с базой данных хостов (узлов сети), поддерживается база данных сетей с аналогичной логикой работы и набором функций: setnetent(), getnetent(), getnetbyaddr(), getnetbyname(), endnetent().

Функция getnetent() обслуживает последовательный доступ к базе, getnetbyaddr() осуществляет поиск по адресному семейству и номеру сети, а getnetbyname() выбирает сеть с заданным (официальным) именем.

Точно такой же программный интерфейс предоставляет база данных сетевых протоколов: setprotoent(), getprotoent(), getprotobyname(), getprotobynumber(), endprotoent().

Еще одно проявление той же логики работы - база данных сетевых сервисов: setservent(), getservent(), getservbyname(), getservbyport(), endservent().

Для создания сокетов, помимо функции socket(), может быть использована функция socketpair(), создающая пару сокетов с установленным между ними соединением. Она обычно используется для адресного семейства AF_UNIX ; поддержка других семейств не гарантируется.

Опросить присвоенный локальный адрес (его иногда называют именем сокета ) можно с помощью функции getsockname().

С сокетами могут быть ассоциированы опции, влияющие на их функционирование. Опросить или изменить значения этих опций помогут функций getsockopt() и setsockopt().

Функция getpeername() позволяет опросить еще одну характеристику - адрес (имя) сокета, с которым установлено соединение.

После привязки сокета к локальному адресу и, возможно, установления соединения и задания значений опций, следует приступать к отправке и/или приему данных через сокет. Для этого служат функции recvfrom(), recv(), recvmsg(), sendto(), send(), sendmsg().

< Лекция 13 || Лекция 14: 12345678910
Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?

Павел Храмцов
Павел Храмцов
Россия
Денис Комаров
Денис Комаров
Россия, Москва