UNIX: разработка сетевых приложений
Шрифт:
Есть несколько важных моментов, которые нужно учитывать при работе с этими очередями.
Аргумент backlogфункции
Беркли-реализации включают поправочный множитель для аргумента
Формального определения аргумента backlog никогда не существовало. В руководстве 4.2BSD сказано, что «он определяет максимальную длину, до которой может вырасти очередь не полностью установленных соединений». Многие руководства и даже POSIX копируют это определение дословно, но в нем не говорится, в каком состоянии должно находится соединение — в состоянии SYN_RCVD, ESTABLISHED (до
Причина возникновения этого множителя теряется в истории [57]. Но если мы рассматриваем backlog как способ задания максимального числа установленных соединений, которые ядро помещает в очередь прослушиваемого сокета (об этом вскоре будет рассказано), этот множитель нужен для учета не полностью установленных соединений, находящихся в очереди [8].
Не следует задавать нулевое значение аргументу
Если трехэтапное рукопожатие завершается нормально (то есть без потерянных сегментов и повторных передач), запись остается в очереди не полностью установленных соединений на время одного периода обращения (round-trip time, RTT), какое бы значение ни имел этот параметр для конкретного соединения между клиентом и сервером. В разделе 14.4 [112] показано, что для одного веб-сервера средний период RTT оказался равен 187 мс. (Чтобы редкие большие числа не искажали картину, здесь использована медиана, а не обычное среднее арифметическое по всем клиентам.)
Традиционно в примерах кода всегда используется значение
В настоящее время многие системы позволяют администраторам изменять максимальное значение аргумента backlog.
Возникает вопрос: какое значение аргумента
Мы приводим простое решение этой проблемы, изменив нашу функцию-обертку для функции
Листинг 4.1. Функция-обертка для функции listen, позволяющая переменной окружения переопределить аргумент backlog
1
Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.
Традиционно в руководствах и книгах утверждалось, что помещение фиксированного числа соединений в очередь позволяет обрабатывать случай загруженного серверного процесса между последовательными вызовами функции
Если очереди заполнены, когда приходит клиентский сегмент SYN, то TCP игнорирует приходящий сегмент SYN [128, с. 930–931] и не посылает RST. Это происходит потому, что состояние считается временным, и TCP клиента должен еще раз передать свой сегмент SYN, для которого в ближайшее время, вероятно, найдется место в очереди. Если бы TCP сервера послал RST, функция
Некоторые реализации отправляют сегмент RST в описанной выше ситуации, что некорректно по изложенным выше причинам. Если вы не пишете клиент специально для работы с подобным сервером, лучше всего игнорировать такую возможность. Ее учет при кодировании клиента снизит его устойчивость и увеличит нагрузку на сеть, если окажется, что порт действительно не прослушивается сервером.
Данные, которые приходят после завершения трехэтапного рукопожатия, но до того, как сервер вызывает функцию
В табл. 4.6 показано действительное число установленных в очередь соединений для различных значений аргумента
Таблица 4.6. Действительное количество соединений в очереди для различных значений аргумента backlog
backlog | MacOS 10.2.6 AIX 5.1 | Linux 2.4.7 | HP-UX 11.11 | FreeBSD 4.8 FreeBSD 5.1 | Solaris 2.9 |
---|---|---|---|---|---|
0 | 1 | 3 | 1 | 1 | 1 |
1 | 2 | 4 | 1 | 2 | 2 |
2 | 4 | 5 | 3 | 3 | 4 |
3 | 5 | 6 | 4 | 4 | 5 |
4 | 7 | 7 | 6 | 5 | 6 |
5 | 8 | 8 | 7 | 6 | 8 |
6 | 10 | 9 | 9 | 7 | 10 |
7 | И | 10 | 10 | 8 | 11 |
8 | 13 | 11 | 12 | 9 | 13 |
9 | 14 | 12 | 13 | 10 | 14 |
10 | 16 | 13 | 15 | 11 | 16 |
11 | 17 | 14 | 16 | 12 | 17 |
12 | 19 | 15 | 18 | 13 | 19 |
13 | 20 | 16 | 19 | 14 | 20 |
14 | 22 | 17 | 21 | 15 | 22 |