Чтение онлайн

на главную - закладки

Жанры

UNIX: разработка сетевых приложений
Шрифт:

POSIX требует наличия только трех элементов структуры:

sin_family
,
sin_addr
и
sin_port
. POSIX-совместимая реализация может определять дополнительные элементы структуры, и это норма для структуры адреса сокета Интернета. Почти все реализации добавляют элемент sin_zero, так что все структуры адреса сокета имеют размер как минимум 16 байт.

Типы элементов

s_addr
,
sin_family
и
sin_port
мы указываем согласно POSIX. Тип данных
in_addr_t
соответствует целому числу без знака длиной как минимум 32 бита,
in_port_t
— целому числу без знака длиной как минимум 16 бит, a
sa_family_t
это произвольное целое число без знака. Последнее обычно представляет собой 8-разрядное целое без знака, если реализация поддерживает поле длины, либо 16-разрядное целое без знака, если поле длины не поддерживается. В табл. 3.1 перечислены эти три типа данных POSIX вместе с некоторыми другими типами данных POSIX, с которыми мы встретимся.

Таблица 3.1. Типы данных, требуемые POSIX

Тип данных Описание Заголовочный файл
int8_t 8-разрядное целое со знаком <sys/types.h>
uint8_t 8-разрядное целое без знака <sys/types.h>
int16_t 16-разрядное целое со знаком <sys/types.h>
uint16_t 16-разрядное целое без знака <sys/types.h>
int32_t 32-разрядное целое со знаком <sys/types.h>
uint32_t 32-разрядное целое без знака <sys/types.h>
sa_family_t семейство адресов структуры адреса сокета <sys/socket.h>
socklen_t длина структуры адреса сокета, обычно типа uint32_t <sys/socket.h>
in_addr_t IPv4-адрес, обычно типа uint32_t <netinet/in.h>
in_port_t порт TCP или UDP, обычно типа uint16_t <netinet/in.h>

Вы также встретите типы данных

u_char
,
u_short
,
u_int
и
u_long
, которые не имеют знака. POSIX определяет их с замечанием, что они устарели. Они предоставляются в целях обратной совместимости.

И адрес IPv4, и номер порта TCP и UDP всегда хранятся в структуре в соответствии с порядком байтов, определенным в сети ( сетевой порядок байтовnetwork byte order). Об этом нужно помнить при использовании этих элементов (более подробно о разнице между порядком байтов узла и порядком байтов в сети мы поговорим в разделе 3.4).

К 32-разрядному адресу IPv4 можно обратиться двумя путями. Например, если

serv
— это структура адреса сокета Интернета, то
serv.sin_addr
указывает на 32-разрядный адрес IPv4 как на структуру
in_addr
, в то время как
serv.sin_addr.s_addr
указывает на тот же 32-разрядный адрес IPv4 как на значение типа
in_addr_t
(обычно это 32-разрядное целое число без знака). Нужно следить за корректностью обращения к адресам IPv4, особенно при использовании их в качестве аргументов различных функций, потому что компиляторы часто передают структуры не так, как целочисленные переменные.

ПРИМЕЧАНИЕ

Причина того, что sin_addr является структурой,

а не просто целым числом без знака, носит исторический характер. В более ранних реализациях (например, 4.2BSD) структура in_addr определялась как объединение (union) различных структур, чтобы сделать возможным доступ к каждому из четырех байтов 32-разрядного IPv4-адреса, а также к обоим входящим в него 16-разрядным значениям. Эта возможность использовалась в адресах классов А, В и С для выборки соответствующих байтов адреса. Но с появлением подсетей и последующим исчезновением различных классов адресов (см. раздел А.4) и введением бесклассовой адресации (classless addressing) необходимость в объединении структур отпала. В настоящее время большинство систем отказались от использования объединения и просто определяют in_addr как структуру, содержащую один элемент типа in_addr_t.

Элемент

sin_zero
не используется, но мы всегдаустанавливаем его в нуль при заполнении одной из этих структур. Перед заполнением структуры мы всегда обнуляем все ее элементы, а не только
sin_zero
.

ПРИМЕЧАНИЕ

В большинстве случаев при использовании этой структуры не требуется, чтобы элемент sin_zero был равен нулю, но, например, при привязке конкретного адреса IPv4 (а не произвольного интерфейса) этот элемент обязательно должен быть нулевым [128, с. 731-732].

Структуры адреса сокета используются только на данном узле: сама структура не передается между узлами, хотя определенные поля (например, поля IP-адреса и порта) используются для соединения.

Универсальная структура адреса сокета

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

Проблема в том, как объявить тип передаваемого указателя. Для ANSI С решение простое:

void*
является указателем на неопределенный (универсальный) тип (generic pointer type). Но функции сокетов существовали до появления ANSI С, и в 1982 году было принято решение определить универсальнуюструктуру адреса сокета (generic socket address structure) в заголовочном файле
<sys/socket.h>
, которая показана в листинге 3.2.

Листинг 3.2. Универсальная структура адреса сокета: sockaddr

struct sockaddr {

uint8_t sa_len;

sa_family_t sa_family; /* семейство адресов: константа AF_xxx */

char sa_data[14]; /* адрес, специфичный для протокола */

};

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

bind
(ANSI С):

int bind(int, struct sockaddr*, socklen_t);

При этом требуется, чтобы для любых вызовов этих функций указатель на структуру адреса сокета, специфичную для протокола, был преобразован в указатель на универсальную структуру адреса сокета. Например:

struct sockaddr_in serv; /* структура адреса сокета IPv4 */

/* заполняем serv{} */

bind(sockfd, (struct sockaddr*)&serv, sizeof(serv));

Если мы не выполним преобразование (

struct sockaddr*
), компилятор С сгенерирует предупреждение в форме
"Warning: passing arg 2 of 'bind' from incompatible pointer type"
(Передается указатель несовместимого типа). Здесь мы предполагаем, что в системных заголовочных файлах имеется прототип ANSI С для функции bind.

Поделиться:
Популярные книги

Моя на одну ночь

Тоцка Тала
Любовные романы:
современные любовные романы
короткие любовные романы
5.50
рейтинг книги
Моя на одну ночь

Черный Маг Императора 8

Герда Александр
8. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 8

Измена. Отбор для предателя

Лаврова Алиса
1. Отбор для предателя
Фантастика:
фэнтези
5.00
рейтинг книги
Измена. Отбор для предателя

Кодекс Крови. Книга II

Борзых М.
2. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга II

Шаг в бездну

Муравьёв Константин Николаевич
3. Перешагнуть пропасть
Фантастика:
фэнтези
космическая фантастика
7.89
рейтинг книги
Шаг в бездну

Часовая битва

Щерба Наталья Васильевна
6. Часодеи
Детские:
детская фантастика
9.38
рейтинг книги
Часовая битва

Вечная Война. Книга II

Винокуров Юрий
2. Вечная война.
Фантастика:
юмористическая фантастика
космическая фантастика
8.37
рейтинг книги
Вечная Война. Книга II

Хроники странного королевства. Вторжение. (Дилогия)

Панкеева Оксана Петровна
110. В одном томе
Фантастика:
фэнтези
9.38
рейтинг книги
Хроники странного королевства. Вторжение. (Дилогия)

Часовой ключ

Щерба Наталья Васильевна
1. Часодеи
Фантастика:
фэнтези
9.36
рейтинг книги
Часовой ключ

Инвестиго, из медика в маги

Рэд Илья
1. Инвестиго
Фантастика:
фэнтези
городское фэнтези
попаданцы
5.00
рейтинг книги
Инвестиго, из медика в маги

Кротовский, может, хватит?

Парсиев Дмитрий
3. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
аниме
7.50
рейтинг книги
Кротовский, может, хватит?

Драконий подарок

Суббота Светлана
1. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
7.30
рейтинг книги
Драконий подарок

Очешуеть! Я - жена дракона?!

Амеличева Елена
Фантастика:
юмористическая фантастика
5.43
рейтинг книги
Очешуеть! Я - жена дракона?!

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9