Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Некоторые серверы, особенно серверы FTP, предоставляют приложению тайм- аут, часто до нескольких минут. Это выполняется самим приложением, обычно при вызове функции read
, когда считывается следующая команда клиента. Этот тайм-аут не связан с данным параметром сокета.
В SCTP имеется механизм проверки пульса (heartbeat), аналогичный механизму проверочных сообщений (keep-alive) TCP. Этот механизм настраивается при помощи элементов параметра сокета SCTP_SET_PEER_ADDR_PARAMS, который будет описан далее, а не при помощи параметра SO_KEEPALIVE. Последний полностью игнорируется сокетом SCTP и не мешает работе механизма проверки пульса.
В табл. 7.3 суммируются различные методы, применяемые для обнаружения того, что происходит на другом конце соединения TCP. Когда мы говорим «использование функции select
для проверки готовности к чтению», мы имеем в виду вызов функции select
для проверки, готов ли сокет для чтения.
Таблица 7.3. Методы определения различных условий TCP
Сценарий | Процесс собеседника выходит из строя | Узел собеседника выходит из строя | Узел собеседника недоступен |
---|---|---|---|
Наш TCP активно посылает данные | TCP собеседника посылает сегмент FIN, что мы можем сразу же обнаружить, используя функцию select для проверки готовности к чтению. Если TCP посылает второй сегмент, TCP собеседника посылает в ответ сегмент RST. Если TCP посылает еще один сегмент, наш TCP посылает сигнал SIGPIPE | По истечении времени ожидания TCP возвращается ошибка ETIMEDOUT | По истечении времени ожидания TCP возвращается ошибка ETIMEDOUT |
Наш TCP активно принимает данные | TCP собеседника посылает сегмент FIN, который мы прочитаем как признак конца файла (возможно, преждевременный) | Мы больше не получаем никаких данных | Мы больше не получаем никаких данных |
Соединение неактивно, посылается пробный пакет | TCP собеседника посылает сегмент FIN, который мы можем сразу же обнаружить, используя функцию select для проверки готовности к чтению | По истечении двух часов отсутствия активности отсылается 9 сообщений для проверки наличия связи с собеседником, а затем возвращается ошибка ETIMEDOUT | По истечении двух часов отсутствия активности отсылается 9 сообщений для проверки наличия связи с собеседником, а затем возвращается ошибка ETIMEDOUT |
Соединение неактивно, не посылается проверочное сообщение | TCP собеседника посылает сегмент FIN, который мы можем сразу же обнаружить, используя функцию select для проверки готовности к чтению | Ничего не происходит | Ничего не происходит |
Параметр сокета SO_LINGER
Этот параметр определяет, как работает функция close
для протоколов, ориентированных на установление соединения (например, TCP и SCTP, но не UDP). По умолчанию функция close
возвращает управление немедленно, но если в отправляющем буфере сокета остаются какие-либо данные, система попытается доставить данные собеседнику.
Параметр сокета SO_LINGER
позволяет нам изменять поведение по умолчанию. Для этого необходимо, чтобы между пользовательским процессом и ядром была передана следующая структура, определяемая в заголовочном файле :
struct linger {
int l_onoff; /* 0=off, ненулевое значение=on */ int l_linger;
/* время ожидания, в POSIX измеряется в секундах */
};
Вызов функции setsockopt
приводит к одному из трех следующих сценариев в зависимости от значений двух элементов структуры linger
.
1. Если l_onoff
имеет нулевое значение, параметр выключается. Значение l_linger
игнорируется и применяется ранее рассмотренный заданный по умолчанию сценарий TCP: функция close
завершается немедленно.
2. Если значение l_onoff
ненулевое, а l_linger
равно нулю, TCP сбрасывает соединение, когда оно закрывается [128, с. 1019–1020], то есть TCP игнорирует все данные, остающиеся в буфере отправки сокета, и отправляет собеседнику сегмент RST, а не обычную последовательность завершения соединения, состоящую из четырех пакетов (см. раздел 2.5). Пример мы покажем в листинге 16.14. Тогда не наступает состояние TCP TIME_WAIT, но из-за этого возникает возможность создания другого воплощения (incarnation) этого соединения в течение 2MSL секунд (удвоенное максимальное время жизни сегмента). Оставшиеся старые дублированные сегменты из только что завершенного соединения могут быть доставлены новому воплощению, что приведет к ошибкам (см. раздел 2.6).
При указанных выше значениях l_onoff
и l_linger
SCTP также выполняет аварийное закрытие сокета, отправляя собеседнику пакет ABORT (см. раздел 9.2 [117]).
Отдельные выступления в Usenet звучат в защиту использования этой возможности, поскольку она позволяет избежать состояния TIME_WAIT и снова запустить прослушивающий сервер, даже если соединения все еще используются с известным портом сервера. Так не нужно делать, поскольку это может привести к искажению данных, как показано в RFC 1337 [11]. Вместо этого перед вызовом функции bind на стороне сервера всегда нужно использовать параметр сокета SO_REUSEADDR, как показано далее. Состояние TIME_WAIT — наш друг, так как оно предназначено для того, чтобы помочь нам дождаться, когда истечет время жизни в сети старых дублированных сегментов. Вместо того, чтобы пытаться избежать этого состояния, следует понять его назначение (см. раздел 2.6).
Тем не менее в некоторых обстоятельствах использование аварийного закрытия может быть оправдано. Одним из примеров является сервер терминалов RS-232, который может навечно зависнуть в состоянии CLOSE_WAIT, пытаясь доставить данные на забитый порт. Если же он получит сегмент RST, он сможет сбросить накопившиеся данные и заново инициализировать порт.
3. Если оба значения — l_onoff
и l_linger
— ненулевые, то при закрытии сокета ядро будет ждать ( linger ) [128, с. 472]. То есть если в буфере отправки сокета еще имеются какие-либо данные, процесс входит в состояние ожидания до тех пор, пока либо все данные не будут отправлены и подтверждены другим концом TCP, либо не истечет время ожидания. Если сокет был установлен как неблокируемый (см. главу 16), он не будет ждать завершения выполнения функции close
, даже если время задержки ненулевое. При использовании этого свойства параметра SO_LINGER
приложению важно проверить значение, возвращаемое функцией close
. Если время ожидания истечет до того, как оставшиеся данные будут отправлены и подтверждены, функция close
возвратит ошибку EWOULDBLOCK
и все данные, оставшиеся в буфере отправки сокета, будут сброшены.
Теперь нам нужно точно определить, когда завершается функция close
на сокете в различных сценариях, которые мы рассмотрели. Предполагается, что клиент записывает данные в сокет и вызывает функцию close
. На рис. 7.1 показана ситуация по умолчанию.
Интервал:
Закладка: