UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Как мы уже говорили, вызов функции
bind
sin_addr
sin_port
sin6_addr
sin6_port
Таблица 4.5. Результаты задания IP-адреса и (или) номера порта в функции bind
Процесс задает | Результат | |
---|---|---|
IP-адрес | Порт | |
Универсальный | 0 | Ядро выбирает IP-адрес и порт |
Универсальный | Ненулевое значение | Ядро выбирает IP-адрес, процесс задает порт |
Локальный | 0 | Процесс задает IP-адрес, ядро выбирает порт |
Локальный | Ненулевое значение | Процесс задает IP-адрес и порт |
Если мы зададим нулевой номер порта, то при вызове функции
bind
В случае IPv4 универсальный адрес, состоящий из символов подстановки (wildcard), задается константой
INADDR_ANY
struct sockaddr_in servaddr;
servaddr sin_addr s_addr = htonl(INADDR_ANY); /* универсальный */
Этот прием работает с IPv4, где IP-адрес является 32-разрядным значением, которое можно представить как простую численную константу (в данном случае 0), но воспользоваться им при работе с IPv6 мы не можем, поскольку 128-разрядный адрес IPv6 хранится в структуре. (В языке С мы не можем поместить структуру в правой части оператора присваивания.) Эта проблема решается следующим образом:
struct sockaddr_in6 serv;
serv sin6_addr = in6addr_any; /* универсальный */
Система выделяет место в памяти и инициализирует переменную
in6addr_any
IN6ADDR_ANY_INIT
in6addr_any
<netinet/in.h>
Значение
INADDR_ANY
htonl
INADDR_
<netinet/in.h>
htonl
Если мы поручаем ядру выбрать для нашего сокета номер динамически назначаемого порта, то функция
bind
bind
const
getsockname
Типичным примером процесса, связывающего с сокетом конкретный IP-адрес, служит узел, на котором работают веб-серверы нескольких организаций (см. раздел 14.2 [112]). Прежде всего, у каждой организации есть свое собственное доменное имя, например
www.organization.com
alias
ifconfig
bind
В качестве альтернативы можно запустить одиночный сервер, связанный с универсальным адресом. Когда происходит соединение, сервер вызывает функцию getsockname, чтобы получить от клиента IP-адрес получателя, который (см. наше обсуждение ранее) может быть равен 198.69.10.128,198.69.10.129 и т.д. Затем сервер обрабатывает запрос клиента па основе именно того IP-адреса, к которому было направлено это соединение.
Одним из преимуществ связывания с конкретным IP-адресом является то, что демультиплексирование данного IP-адреса с процессом сервера выполняется ядром.
Следует внимательно относиться к различию интерфейса, на который приходит пакет, и IP-адреса получателя этого пакета. В разделе 8.8 мы поговорим о моделях систем с гибкой привязкой (weak end system) и с жесткой привязкой (strong end system). Большинство реализаций используют первую модель, то есть считают обычным явлением принятие пакета на интерфейсе, отличном от указанного в IP-адресе получателя. (При этом подразумевается узел с несколькими сетевыми интерфейсами.) При связывании с сокетом конкретного IP-адреса на этом сокете будут приниматься дейтаграммы с заданным IP-адресом получателя, и только они. Никаких ограничений на принимающий интерфейс не накладывается — эти ограничения возникают только в случае, если используется модель системы с жесткой привязкой.
Общей ошибкой выполнения функции
bind
EADDRINUSE
SO_REUSEADDR
SO_REUSEPORT
4.5. Функция listen
Функция
listen
1. Когда сокет создается с помощью функции
socket
connect
listen
listen