Когда подключенный сокет UDP будет закрыт ОС? - PullRequest
2 голосов
/ 28 апреля 2011

У меня есть дескриптор файла UDP в программе C ++, работающей под Linux.Я вызываю connect(), чтобы подключить его к удаленному адресу, а затем выполняю чтение и запись из этого сокета.

Согласно Сетевое программирование UNIX , «Асинхронные ошибки возвращаются процессуподключенные UDP-сокеты. "Я предполагаю, что эти асинхронные ошибки приведут к закрытию сокета UDP операционной системой, но книга не настолько ясна.Также не ясно, какие типы асинхронных ошибок возможны, хотя предполагается, что если порт на удаленной машине не открыт, сокет будет закрыт.

Поэтому мой вопрос: при каких условияхЛи Linux закрыть дескриптор файла UDP?

  • Неверный номер порта?
  • Неправильный IP-адрес?
  • Есть еще кто-нибудь?

Ответы [ 3 ]

5 голосов
/ 28 апреля 2011

connect () на сокете UDP просто записывает номер порта и IP-адрес, который вы передаете, поэтому он будет принимать пакеты только с этого IP / порта, и вы можете использовать сокет fd для отправки / записи данных без указанияудаленный адрес для каждого звонка отправки / записи.

В связи с этим асинхронные ошибки означают, что если вы что-то отправили (), и этот вызов отправки вызвал ошибку, возникшую позже (например, когда стек TCP / IP фактически отправляет пакет или позже возвращается пакет ICMP)последующая отправка вернет эту ошибку.Такие асинхронные ошибки возвращаются только в «подключенный» UDP-сокет.(Справочная страница linux udp (7) предполагает, что ошибки возвращаются независимо от того, подключен сокет или нет, но тестирование показывает, что это не те случаи, когда отправленный UDP-пакет генерирует ошибку ICMP. Возможно, возвращаются ошибки send ()если в этом сокете recv () вместо последующих вызовов send () выдает ошибку)

Сокет не закрыт, однако вам придется закрывать его самостоятельно, вызывая close () или выходя изпрограмма.например, если вы подключаете () свой сокет UDP и отправляете на порт, который никто не слушает, пакет ICMP обычно возвращается, и последующий вызов send () завершится неудачно, а для errno установлено значение ECONNREFUSED.Вы можете продолжить отправку через этот сокет, но ОС не закрывает его, и если кто-то начнет слушать порт в то же время, когда пакеты пройдут.

5 голосов
/ 28 апреля 2011

UDP-сокеты не имеют соединения, поэтому к ним не прилагается никакого реального состояния «открытости» - в отличие от TCP-сокетов, где сокет может находиться в любом количестве состояний соединения, что определяется обменом пакетами до заданного точка.

Единственный смысл, в котором UDP-сокеты можно открывать и закрывать, заключается в том, что они являются объектами системного уровня с некоторым внутренним состоянием и дескриптором файла. Сокеты никогда не закрываются автоматически в случае ошибки и остаются открытыми бесконечно, если только их собственный процесс не завершится или не вызовет close для них.

Для решения вашей другой проблемы, если порт назначения на хосте назначения не открыт, отправитель пакета UDP никогда не узнает. ** UDP не предоставляет никаких средств подтверждения приема получателем. Пакет маршрутизируется и, если он поступает на хост, проверяется на правильность и либо успешно принимается, либо отбрасывается. Существует ряд причин, по которым send может возвращать код ошибки при записи в UDP-сокет, но ни одна из них не связана с состоянием принимающего хоста. ** Я рекомендую обратиться к справочной странице sendto для возможных режимов отказа.

С другой стороны, в случае, если сокет TCP пытается подключиться к неоткрытому порту, отправитель никогда не получит подтверждение своего первоначального запроса на подключение, и в конечном итоге connect не удастся. На этом этапе отправитель может прекратить отправку данных через сокет (поскольку это приведет только к большему количеству ошибок), но даже в этом случае дескриптор файла сокета никогда не закрывается автоматически.

** См. Ответ @Zuljin в комментариях.

1 голос
/ 29 апреля 2011

ОС не закроет ваш сокет только потому, что произошла ошибка.Если другой конец исчезнет, ​​вы можете продолжать отправлять на него сообщения (но могут получать дальнейшие ошибки).

...