UNIX: разработка сетевых приложений
Шрифт:
Таблица 4.5. Результаты задания IP-адреса и (или) номера порта в функции bind
Процесс задает | Результат | |
---|---|---|
IP-адрес | Порт | |
Универсальный | 0 | Ядро выбирает IP-адрес и порт |
Универсальный | Ненулевое значение | Ядро выбирает IP-адрес, процесс задает порт |
Локальный | 0 | Процесс задает IP-адрес, ядро выбирает порт |
Локальный | Ненулевое значение | Процесс задает IP-адрес и порт |
Если мы зададим нулевой номер порта,
В случае IPv4 универсальныйадрес, состоящий из символов подстановки (wildcard), задается константой
Этот прием работает с IPv4, где IP-адрес является 32-разрядным значением, которое можно представить как простую численную константу (в данном случае 0), но воспользоваться им при работе с IPv6 мы не можем, поскольку 128-разрядный адрес IPv6 хранится в структуре. (В языке С мы не можем поместить структуру в правой части оператора присваивания.) Эта проблема решается следующим образом:
Система выделяет место в памяти и инициализирует переменную
Значение
Если мы поручаем ядру выбрать для нашего сокета номер динамически назначаемого порта, то функция
Типичным примером процесса, связывающего с сокетом конкретный IP-адрес, служит узел, на котором работают веб-серверы нескольких организаций (см. раздел 14.2 [112]). Прежде всего, у каждой организации есть свое собственное доменное имя, например
В качестве альтернативы можно запустить одиночный сервер, связанный с универсальным адресом. Когда происходит соединение, сервер вызывает функцию 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-адресом получателя, и только они. Никаких ограничений на принимающий интерфейс не накладывается — эти ограничения возникают только в случае, если используется модель системы с жесткой привязкой.Общей ошибкой выполнения функции
4.5. Функция listen
Функция
1. Когда сокет создается с помощью функции
2. Второй аргумент этой функции задает максимальное число соединений, которые ядро может помещать в очередь этого сокета.
Эта функция обычно вызывается после функций
Чтобы уяснить смысл аргумента
1. Очередь не полностью установленных соединений( incomplete connection queue), содержащую запись для каждого сегмента SYN, пришедшего от клиента, для которого сервер ждет завершения трехэтапного рукопожатия TCP. Эти сокеты находятся в состоянии SYN_RCVD (см. рис. 2.4).
2. Очередь полностью установленных соединений( complete connection queue), содержащую запись для каждого клиента, с которым завершилось трехэтапное рукопожатие TCP. Эти сокеты находятся в состоянии ESTABLISHED (см. рис. 2.4).
На рис. 4.2 представлены обе эти очереди для прослушиваемого сокета.
Рис. 4.2. Две очереди, поддерживаемые прослушиваемым сокетом TCP
Когда в очередь не полностью установленных соединений добавляется новая запись, параметры прослушиваемого сокета копируются на создаваемое соединение. Механизм создания соединения полностью автоматизирован, и процесс сервера в нем не участвует. На рис. 4.3 показан обмен пакетами во время установления соединения с использованием этих очередей.
Рис. 4.3. Обмен пакетами в процессе установления соединения с применением очередей
Когда от клиента приходит сегмент SYN, TCP создает новую запись в очереди не полностью установленных соединений, а затем отвечает вторым сегментом трехэтапного рукопожатия, посылая сегмент SYN вместе с сегментом ACK, подтверждающим прием клиентского сегмента SYN (см. раздел 2.6). Эта запись останется в очереди не полностью установленных соединений, пока не придет третий сегмент трехэтапного рукопожатия (клиентский сегмент ACK для сегмента сервера SYN) или пока не истечет время жизни этой записи. (В реализациях, происходящих от Беркли, время ожидания (тайм-аут) для элементов очереди не полностью установленных соединений равно 75 с.) Если трехэтапное рукопожатие завершается нормально, запись переходит из очереди не полностью установленных соединений в конец очереди полностью установленных соединений. Когда процесс вызывает функцию