Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

Таблица 8.2. Сокеты TCP и UDP: может ли быть задан адрес протокола получателя

Тип сокета write или send sendto, без указания получателя sendto, с указанием получателя
Сокет TCP Да Да EISCONN
Сокет UDP, присоединенный Да Да EISCONN
Сокет UDP, неприсоединенный EDESTADDRREQ EDESTADDRREQ Да
ПРИМЕЧАНИЕ

POSIX определяет, что операция вывода, не задающая адрес получателя на неприсоединенном сокете UDP, должна возвращать ошибку ENOTCONN, а не EDESTADDRREQ.

Solaris 2.5 допускает функцию sendto, которая задает адрес получателя для присоединенного сокета UDP. POSIX определяет, что в такой ситуации должна возвращаться ошибка EISCONN.

На рис. 8.7 обобщается информация о присоединенном сокете UDP.

Рис. 8.7. Присоединенный сокет UDP

Приложение вызывает функцию

connect
, задавая IP-адрес и номер порта собеседника. Затем оно использует функции
read
и
write
для обмена данными с собеседником.

Дейтаграммы, приходящие с любого другого IP-адреса или порта (который мы обозначаем как «???» на рис. 8.7), не передаются на присоединенный сокет, поскольку либо IP-адрес, либо UDP-порт отправителя не совпадают с адресом протокола, с которым сокет соединяется с помощью функции

connect
. Эти дейтаграммы могут быть доставлены на какой-то другой сокет UDP на узле. Если нет другого совпадающего сокета для приходящей дейтаграммы, UDP проигнорирует ее и сгенерирует ICMP-сообщение о недоступности порта.

Обобщая вышесказанное, мы можем утверждать, что клиент или сервер UDP может вызвать функцию

connect
, только если этот процесс использует сокет UDP для связи лишь с одним собеседником. Обычно именно клиент UDP вызывает функцию
connect
, но существуют приложения, в которых сервер UDP связывается с одним клиентом на длительное время (например, TFTP), и в этом случае и клиент, и сервер вызывают функцию
connect
.

Еще один пример долгосрочного взаимодействия — это DNS (рис. 8.8).

Рис. 8.8. Пример клиентов и серверов DNS и функции connect

Клиент DNS может быть сконфигурирован для использования одного или более серверов, обычно с помощью перечисления IP-адресов серверов в файле

/etc/resolv.conf
. Если в этом файле указан только один сервер (на рисунке этот клиент изображен в крайнем слева прямоугольнике), клиент может вызвать функцию connect, но если перечислено множество серверов (второй справа прямоугольник на рисунке), клиент не может вызвать функцию
connect
. Обычно сервер DNS обрабатывает также любые клиентские запросы, следовательно, серверы не могут вызывать функцию
connect
.

Многократный вызов функции connect для сокета UDP

Процесс с присоединенным сокетом UDP может снова вызвать функцию

connect
Для этого сокета, чтобы:

задать новый IP-адрес и порт;

отсоединить сокет.

Первый случай, задание нового собеседника для присоединенного сокета UDP, отличается от использования функции

connect
с сокетом TCP: для сокета TCP функция
connect
может быть вызвана только один раз.

Чтобы отсоединить сокет UDP, мы вызываем функцию

connect
, но присваиваем элементу семейства структуры адреса сокета (
sin_family
для IPv4 или
sin6_family
для IPv6) значение
AF_UNSPEC
. Это может привести к ошибке
EAFNOSUPPORT
[128, с. 736], но это нормально. Именно процесс вызова функции
connect
на уже присоединенном сокете UDP позволяет отсоединить сокет [128, с. 787–788].

ПРИМЕЧАНИЕ

В руководстве BSD по поводу функции connect традиционно говорилось: «Сокеты дейтаграмм могут разрывать связь, соединяясь с недействительными адресами, такими как пустые адреса». К сожалению, ни в одном руководстве не сказано, что представляет собой «пустой адрес», и не упоминается, что в результате возвращается ошибка (что нормально). Стандарт POSIX явно указывает, что семейство адресов должно быть установлено в AF_UNSPEC, но затем сообщает, что этот вызов функции connect может возвратить, а может и не возвратить ошибку EAFNOSUPPORT.

Производительность

Когда приложение вызывает функцию

sendto
на неприсоединенном сокете UDP, ядра реализаций, происходящих от Беркли, временно соединяются с сокетом, отправляют дейтаграмму и затем отсоединяются от сокета [128, с. 762–763]. Таким образом, вызов функции
sendto
для последовательной отправки двух дейтаграмм на неприсоединенном сокете включает следующие шесть шагов, выполняемых ядром:

присоединение сокета;

вывод первой дейтаграммы;

  • Читать дальше
  • 1
  • ...
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: