UNIX: разработка сетевых приложений
solaris % <b>sock -s -u 8888 &</b> <i>запускаем первый</i>[1] 24051solaris % <b>sock -s -u 8888</b>can't bind local address: Address already in usesolaris % <b>sock -s -u -A 8888 &</b> <i>снова пробуем запустить второй с -A:</i><i> работает</i>solaris % <b>netstat -na | grep 8888</b> <i>мы видим дублированное связывание</i>*.8888 Idle* 8888 IdleВ этой системе задавать параметр
было необходимо только для второго связывания. Наконец, запускаем сценарий в MacOS X 10.2.6, где поддерживается как многоадресная передача, так и параметрSO_REUSEADDR. Сначала пробуем использоватьSO_REUSEPORTдля обоих серверов, но это не работает.SO_REUSEADDRmacosx % <b>sock -u -s -A 7777 &</b>[1] 17610macosx % <b>sock -u -s -A 7777</b>can't bind local address: Address already in useТогда пробуем использовать параметр
только для второго сервера. Это также не работает, так как полностью дублированное связывание требует включения данного параметра для всех сокетов, совместно использующих соединение.SO_REUSEPORTmacosx % <b>sock -u -s 8888 &</b>[1] 17612macosx % <b>sock -u -s -T 8888</b>can't bind local address: Address already in useНаконец, задаем параметр
для обоих серверов, и этот вариант работает.SO_REUSEPORTmacosx % <b>sock -u -s -Т 9999 &</b>[1] 17614macosx % <b>sock -u -s -T 9999 &</b>[2] 17615macosx % <b>netstat -na | grep 9999</b>udp4 0 0 *.9999 *.*udp4 0 0 *.9999 *.*7.7. Этот параметр (
) не делает ничего, поскольку программа-dиспользует ICMP-сокет, а параметр сокетаpingвлияет только на TCP-сокеты. Описание параметра сокетаSO_DEBUGвсегда было довольно расплывчатым, наподобие «этот параметр допускает отладку на соответствующем уровне протокола», и единственный уровень протокола, где реализуется данный параметр — это TCP.SO_DEBUG7.8. Временная диаграмма приведена на рис. Д.4.
Рис. Д.4. Взаимодействие алгоритма Нагла с задержанными сегментами ACK
7.9. Установка параметра сокета
приводит к немедленной отправке данных из второй функцииTCP_NODELAY, даже если имеется еще один небольшой пакет, ожидающий отправки. Это показано на рис. Д.5. Полное время в данном примере превышает 150 мс.writeРис Д.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 большую часть времени блокирован в вызове функции
, а дочерний процесс в листинге 5.2 большую часть времени блокирован в вызове функцииaccept, который содержится в функцииread. Проверка работоспособности с помощью параметраreadlineне влияет на прослушиваемый сокет, поэтому в случае, если клиентский узел выйдет из строя, родительский процесс не пострадает. Функция read дочернего процесса возвратит ошибкуSO_KEEPALIVEпримерно через 2 ч после последнего обмена данными через соединение.ETIMEDOUT7.13. Клиент, приведенный в листинге 5.4, большую часть времени блокирован вызовом функции
, который, в свою очередь, блокирован операцией чтения из стандартной библиотеки ввода-вывода на стандартном устройстве ввода. Когда примерно через 2 ч после последнего обмена данными через соединение истечет время таймера проверки работоспособности и проверочные сообщения не выявят работоспособности сервера, ошибка сокета, ожидающая обработки, примет значениеfgets. Но клиент блокирован вызовом функцииETIMEDOUT, поэтому он не увидит этой ошибки, пока не осуществит чтение или запись на сокете. Это одна из причин, по которой в главе 6 листинг 5.4 был изменен таким образом, чтобы использовать функциюfgets.select7.14. Этот клиент большую часть времени блокирован вызовом функции
, которая сообщит, что сокет готов для чтения, как только ожидающая обработки ошибка будет установлена вselect(как показано в предыдущем решении).ETIMEDOUT7.15. Происходит обмен только двумя сегментами, а не четырьмя. Вероятность того, что таймеры двух систем будут строго синхронизированы, очень мала, следовательно, на одном конце соединения таймер проверки работоспособности сработает немного раньше, чем на другом. Первый из сработавших таймеров посылает проверочное сообщение, заставляя другой конец послать в ответ сегмент ACK. Но получение проверочного сообщения приводит к тому, что таймеру проверки работоспособности с более медленными часами будет присвоено новое значение — он сдвинется на 2 ч вперед.
7.16 Изначально в API сокетов не было функции
. Вместо этого четвертый аргумент функцииlistenсодержал параметр сокета, а параметрsocketиспользовался для задания прослушиваемого сокета. Когда добавилась функцияSO_ACCEPTCONN, флаг остался, но теперь его может устанавливать только ядро [128, с. 456].listenГлава 8
8.1. Да. Функция
возвращает 4096 байт данных, а функцияreadвозвращает 2048 байт (первую из двух дейтаграмм). Функцияrecvfromна сокете дейтаграмм никогда не возвращает больше одной дейтаграммы, независимо от того, сколько приложение запрашивает.recvfrom


