Michael J. Donahoo "TCP/IP Sockets in C, 2nd Edition" / Michael J. Donahoo "Программирование TCP/IP сокетов в Си, 2-ое издание": 2.4 Указание адресов
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
2.4 Указание адресов prefer211 22.05.12 в 15:57 |
|
|
Приложения, использующие сокеты, нуждаются в возможности идентификации удаленных точек, с которыми они будут взаимодействовать. victor8632 31.05.12 в 06:07 |
||
|
Из предыдущего следует, что клиент должен указать адрес и номер порта сервера приложений, с которыми он собирается взаимодействовать. victor8632 31.05.12 в 06:15 |
||
|
Кроме того, уровень сокетов иногда требует передачи адресов в приложение. victor8632 31.05.12 в 06:18 |
||
|
Например, функция, аналогичная "Запрос ID" в телефонной сети позволяет серверу узнать адрес и номер порта для каждого клиента, который общается с ним. victor8632 31.05.12 в 06:20 |
||
|
В этом разделе мы рассмотрим структуры данных, используемые в качестве контейнеров для этой информации в Sockets API. victor8632 31.05.12 в 06:22 |
||
|
2.4.1 Общие адерса victor8632 31.05.12 в 06:24 |
||
|
Sockets API определяет общий тип данных - структуру sockaddr - для определения адресов, связанных с сокетами: victor8632 31.05.12 в 06:27 |
||
|
struct sockaddr { victor8632 07.06.12 в 10:23 |
||
|
Первая часть этой адресной структуры определяет схему адресации - адресное пространство, к которому принадлежит адрес. victor8632 07.06.12 в 10:26 |
||
|
Для наших целей мы будем использовать системно независимые константы af_inet и af_inet6, которые будут определять семейство интернет адресов IPv4 и IPv6 соответственно. victor8632 05.07.12 в 11:25 |
||
|
Вторая часть структуры является последовательностью бит, конкретный вид которых зависит от семейства адресов. (Это типичный способ борьбы с неоднородностью в операционных системах и сетях.) victor8632 11.07.12 в 12:39 |
||
|
Как мы обсуждали в пункте 1.2, адрес сокета для семейства протоколов интернета имеет две части: 32-битный (IPv4) или 128-битный (IPv6) интернет адрес и 16-битный номер порта [Внимательный читатель может заметить, что общая структура sockaddr не сможет вместить в себя 16-байтный IPv6 адрес и 2-байтный номер порта. Мы еще столкнемся с этой трудностью в ближайшее время.]. victor8632 11.07.12 в 12:49 |
||
|
2.4.2 IPv4 адреса victor8632 31.05.12 в 06:24 |
||
|
Конкретный вид структуры sockaddr, который используется в для TCP/IP адресов сокетов, зависит от версии IP. Для IPv4 используется структура sockaddr_in. victor8632 05.07.12 в 11:28 |
||
|
struct in_addr { victor8632 05.07.12 в 11:29 |
||
|
Как вы видите, структура sockaddr_in имеет поля для номера порта и интернет адреса в дополнение к полю адресного семейства. victor8632 11.07.12 в 12:51 |
||
|
Важно понимать, что sockaddr_in это более подробное представление данных, содержащихся в структуре sockaddr, с учетом использования сокетов IPv4. victor8632 07.09.12 в 07:29 |
||
|
Таким образом, мы можем заполнить поля структуры sockaddr_in и потом поместить ее (или указатель на нее) вместо sockaddr (или указателя уже на эту структуру) в функции сокета, которые по полю sa_family будут определять фактический тип структуры, а затем сможем вернуться к соответствующему типу. victor8632 17.09.12 в 13:35 |
||
|
2.4.3 IPv6 адреса victor8632 04.07.12 в 14:19 |
||
|
В случае IPv6 используется структура sockaddr_in6. victor8632 04.07.12 в 14:20 |
||
|
struct in_addr { victor8632 17.09.12 в 13:38 |
||
|
Структура sockaddr_in6 имеет дополнительные поля помимо тех, которые есть в структуре sockaddr_in. victor8632 17.09.12 в 13:40 |
||
|
Они предназначены для реализации возможностей протокола IPv6, которые обычно не используются. Они будут (в основном) игнорироваться в этой книге. victor8632 17.09.12 в 13:43 |
||
|
Как и в случае со структурой sockaddr_in, мы должны использовать структуру sockaddr_in6 (указатель на нее) вместо структуры sockaddr (указателя на нее) в различных функциях сокета. victor8632 25.09.12 в 13:04 |
||
|
Опять же, программная реализация использует поле адреса семейства адресов для определения реального типа аргумента. victor8632 25.09.12 в 13:06 |
||
|
2.4.4 Основы хранения адресов victor8632 25.09.12 в 13:09 |
||
|
Если вы что-нибудь знаете о размещении структур данных в С, вы, возможно, уже заметили что структура sockaddr не является достаточно большой, чтобы в ней разместилась структура sockaddr_in6. victor8632 26.12.12 в 12:39 |
||
|
(Если вы ничего об этом не знаете, не огорчайтесь: многое из того, что вам нужно знать, будет рассмотрено в главе 5.) victor8632 26.12.12 в 12:40 |
||
|
В частности, что, если мы хотим выделить место для структуры адреса, но не знаем фактического типа адреса (т.е. IPv4 или IPv6)? Основная структура sockaddr не будет работать, так как она является слишком маленькой для некоторых типов адресов. victor8632 26.12.12 в 12:48 |
||
|
[Вы можете удивиться, почему это так (почему мы так делаем). Причины, очевидно, имеют отношение к обратной совместимости: API сокетов было создано достаточно давно, до возникновения IPv6, когда ресурсы были ограниченными и не было никакой необходимости иметь структуру адреса большого размера. Изменение ее размера сейчас на больший, по-видимому, нарушит двоичную совместимость с некоторыми приложениями.] victor8632 26.12.12 в 13:01 |
||
|
Для решения этой проблемы проектировщики сокетов создали структуру sockaddr_storage, которая которая гарантированно будет такого размера, чтобы вместить все поддерживаемые типы адресов. victor8632 26.12.12 в 12:52 |
||
|
struct sockaddr_storage { victor8632 25.09.12 в 13:13 |
||
|
Как и в структуре sockaddr, мы имеем здесь первое поле, определяющее фактический тип адреса; однако в структуре sockaddr_storage у нас есть достаточно места для любого типа адреса. victor8632 26.12.12 в 13:06 |
||
|
(Для получения представления о том, как это может быть достигнуто, обратитесь к обсуждению того, как компилятор C размещает структуры в памяти, в разделе 5.1.6.) victor8632 26.12.12 в 13:09 |
||
|
И последнее замечание по адресам. На некоторых платформах, структуры адреса содержат дополнительное поле, в котором хранится длина структуры адреса в байтах. victor8632 26.12.12 в 13:12 |
||
|
Для структур sockaddr, sockaddr_in, sockaddr_in6 и sockaddr_storage дополнительные поля называются sa_len, sin_len, sin6_len и ss_len соотвественно. victor8632 26.12.12 в 13:14 |
||
|
Так как поле длины имеется не во всех системах, не используйте его. victor8632 26.12.12 в 13:16 |
||
|
Как правило, для платформ с этой формой структуры определяют специальное значение (например, sin6_len), которое может быть проверено во время компиляции, чтобы узнать, существует ли поле длины структуры. victor8632 26.12.12 в 13:21 |
||
|
2.4.5 Бинарные/Строковые преобразования адресов victor8632 25.09.12 в 13:13 |
||
|
Для функций сокетов адреса должны быть представлены в "числовой" (т.е. бинарной) форме, однако для человека больше подходит стрка с "версией для печати" (например, 192.168.1.1 или 1::1). victor8632 26.12.12 в 13:38 |
||
|
Мы можем преобразовать адрес из печатной строки к числовому виду при помощи функции inet_pton() (pton = printable to numeric - печатное к числовому): victor8632 26.12.12 в 13:26 |
||
|
int inet_pton(int addressFamily, const char *src, void *dst) victor8632 25.09.12 в 13:11 |
||
|
Первый параметр, addressFamily, определяет семейство адресов, в которое нужно конвертировать. victor8632 25.09.12 в 13:16 |
||
|
Напомним, что Sockets API предоставляет общий интерфейс для большого числа областей связи. victor8632 26.12.12 в 13:29 |
||
|
Тем не менее здесь нас интересуют только IPv4 (af_inet) и IPv6 (af_inet6). victor8632 26.12.12 в 13:31 |
||
|
Параметр src является ссылкой на заканчивающуюся символом '\0' строку, содержащую адрес, который нужно преобразовать. victor8632 26.12.12 в 13:34 |
||
|
Параметр dst указывает на блок памяти в пространстве вызова, зарезервированный для результата: его величина должна быть достаточной для хранения результата (по крайней мере 4 байта для IPv4 и 16 байт для IPv6). victor8632 15.04.13 в 12:59 |
||
|
inet_pton() возвращает 1, если преобразование произошло успешно, при этом dst указывает на адрес в сетевом байтовом представлении; 0, если строка, на которую указывает src не отформатирована должным образом; и -1, если указанное семейство адресов неизвестно. victor8632 15.04.13 в 13:08 |
||
|
Мы можем пойти другим путем для конвертации адреса из числовой в печатную форму, воспользовавшись функцией inet_ntop() (ntop = numeric to printable - от числа к печатному представлению): victor8632 15.04.13 в 13:11 |
