UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
2. Второй аргумент этой функции задает максимальное число соединений, которые ядро может помещать в очередь этого сокета.
#include <sys/socket.h>
int listen(int <i>sockfd</i>, int <i>backlog</i>);
<i>Возвращает: 0 в случае успешного выполнения, -1 в случае ошибки</i>
Эта функция обычно вызывается после функций
socket
bind
accept
Чтобы уяснить смысл аргумента
backlog
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 с.) Если трехэтапное рукопожатие завершается нормально, запись переходит из очереди не полностью установленных соединений в конец очереди полностью установленных соединений. Когда процесс вызывает функцию
accept
Есть несколько важных моментов, которые нужно учитывать при работе с этими очередями.
■ Аргумент backlog функции
listen
■ Беркли-реализации включают поправочный множитель для аргумента
backlog
backlog
Формального определения аргумента backlog никогда не существовало. В руководстве 4.2BSD сказано, что «он определяет максимальную длину, до которой может вырасти очередь не полностью установленных соединений». Многие руководства и даже POSIX копируют это определение дословно, но в нем не говорится, в каком состоянии должно находится соединение — в состоянии SYN_RCVD, ESTABLISHED (до вызова accept), или же в любом из них. Определение, приведенное выше, относится к реализации Беркли 4.2BSD, и копируется многими другими реализациями.
Причина возникновения этого множителя теряется в истории [57]. Но если мы рассматриваем backlog как способ задания максимального числа установленных соединений, которые ядро помещает в очередь прослушиваемого сокета (об этом вскоре будет рассказано), этот множитель нужен для учета не полностью установленных соединений, находящихся в очереди [8].
■ Не следует задавать нулевое значение аргументу
backlog
■ Если трехэтапное рукопожатие завершается нормально (то есть без потерянных сегментов и повторных передач), запись остается в очереди не полностью установленных соединений на время одного периода обращения (round-trip time, RTT), какое бы значение ни имел этот параметр для конкретного соединения между клиентом и сервером. В разделе 14.4 [112] показано, что для одного веб-сервера средний период RTT оказался равен 187 мс. (Чтобы редкие большие числа не искажали картину, здесь использована медиана, а не обычное среднее арифметическое по всем клиентам.)
■ Традиционно в примерах кода всегда используется значение
backlog
backlog
В настоящее время многие системы позволяют администраторам изменять максимальное значение аргумента backlog.
■ Возникает вопрос: какое значение аргумента
backlog
Мы приводим простое решение этой проблемы, изменив нашу функцию-обертку для функции
listen
LISTENQ
Листинг 4.1. Функция-обертка для функции listen, позволяющая переменной окружения переопределить аргумент backlog
//lib/wrapsock.c