can't bind local address: Address already in use
solaris %
sock -s -u -A 8888
solaris %
netstat -na | grep 8888
*.8888 Idle
* 8888 Idle
В этой системе задавать параметр
SO_REUSEADDR
было необходимо только для второго связывания. Наконец, запускаем сценарий в MacOS X 10.2.6, где поддерживается как многоадресная передача, так и параметр
SO_REUSEPORT
. Сначала пробуем использовать
SO_REUSEADDR
для обоих серверов, но это не работает.
macosx %
sock -u -s -A 7777
[1] 17610
macosx %
sock -u -s -A 7777
can't bind local address: Address already in use
Тогда пробуем использовать параметр
SO_REUSEPORT
только для второго сервера. Это также не работает, так как полностью дублированное связывание требует включения данного параметра для всех сокетов, совместно использующих соединение.
macosx %
sock -u -s 8888
[1] 17612
macosx %
sock -u -s -T 8888
can't bind local address: Address already in use
Наконец, задаем параметр
SO_REUSEPORT
для обоих серверов, и этот вариант работает.
macosx %
sock -u -s -Т 9999
[1] 17614
macosx %
sock -u -s -T 9999
[2] 17615
macosx %
netstat -na | grep 9999
udp4 0 0 *.9999 *.*
udp4 0 0 *.9999 *.*
7.7. Этот параметр (
-d
) не делает ничего, поскольку программа
ping
использует ICMP-сокет, а параметр сокета
SO_DEBUG
влияет только на TCP-сокеты. Описание параметра сокета
SO_DEBUG
всегда было довольно расплывчатым, наподобие «этот параметр допускает отладку на соответствующем уровне протокола», и единственный уровень протокола, где реализуется данный параметр — это TCP.
7.8. Временная диаграмма приведена на рис. Д.4.
Рис. Д.4. Взаимодействие алгоритма Нагла с задержанными сегментами ACK
7.9. Установка параметра сокета
TCP_NODELAY
приводит к немедленной отправке данных из второй функции
write
, даже если имеется еще один небольшой пакет, ожидающий отправки. Это показано на рис. Д.5. Полное время в данном примере превышает 150 мс.
Рис Д.5. Предотвращение алгоритма Нагла путем установки параметра TCP_NODELAY
7.10. Как показано на рис. Д.6, преимущество данного решения состоит в уменьшении числа пакетов.
Рис. Д.6. Использование функции writev вместо параметра сокета TCP_NODELAY
7.11. В разделе 4.2.3.2 говорится: «задержка ДОЛЖНА быть меньше 0,5 с, а в потоке полноразмерных сегментов СЛЕДУЕТ использовать сегмент ACK по крайней мере для каждого второго сегмента». Беркли-реализации задерживают сегмент ACK не более, чем на 200 мс [128, с. 821].
7.12. Родительский процесс сервера в листинге 5.1 большую часть времени блокирован в вызове функции
accept
, а дочерний процесс в листинге 5.2 большую часть времени блокирован в вызове функции
read
, который содержится в функции
readline
. Проверка работоспособности с помощью параметра
SO_KEEPALIVE
не влияет на прослушиваемый сокет, поэтому в случае, если клиентский узел выйдет из строя, родительский процесс не пострадает. Функция read дочернего процесса возвратит ошибку
ETIMEDOUT
примерно через 2 ч после последнего обмена данными через соединение.
7.13. Клиент, приведенный в листинге 5.4, большую часть времени блокирован вызовом функции
fgets
, который, в свою очередь, блокирован операцией чтения из стандартной библиотеки ввода-вывода на стандартном устройстве ввода. Когда примерно через 2 ч после последнего обмена данными через соединение истечет время таймера проверки работоспособности и проверочные сообщения не выявят работоспособности сервера, ошибка сокета, ожидающая обработки, примет значение
ETIMEDOUT
. Но клиент блокирован вызовом функции
fgets
, поэтому он не увидит этой ошибки, пока не осуществит чтение или запись на сокете. Это одна из причин, по которой в главе 6 листинг 5.4 был изменен таким образом, чтобы использовать функцию
select
.
7.14. Этот клиент большую часть времени блокирован вызовом функции
select
, которая сообщит, что сокет готов для чтения, как только ожидающая обработки ошибка будет установлена в
ETIMEDOUT
(как показано в предыдущем решении).