UDP и сокеты, recvfrom (), возвращающий -1 и ресурс временно недоступен - PullRequest
7 голосов
/ 04 марта 2010

У меня есть клиент и сервер, взаимодействующий с дейтаграммами (UDP) на C. Клиент отправляет 5 сообщений, а после получения сообщений сервер отправляет сообщения обратно. Прием и отправка сообщений хороши, пока клиент не закончил получать сообщения. После того, как сервер отправил все сообщения обратно, он завершает работу с помощью close (). поэтому recvfrom () из клиента должен возвращать 0, верно?

Предполагая, что recvfrom () должен возвращать 0 при close () со стороны сервера, вместо этого он возвращает -1, а ошибка Resource временно недоступна. Является ли этот ресурс ссылкой на закрытый сокет с сервера? Или это для чего-то совершенно другого, такого как исчерпание буфера или что-то (что я не думаю, правда)?

Предполагая, что мое предположение было неверным и -1 возвращается, поскольку сервер завершен, я, вероятно, должен обработать ошибку с помощью

if(SOMEMACRO)
   do something 

Как мне узнать, что такое SOMEMACRO? Я распечатываю ошибку, но там говорится, что ресурс недоступен, а в описании recvfrom () нет информации о недоступном ресурсе ..?

Кстати, это неблокирующий сокет, если это имеет какое-то значение, так как я прочитал, что если установлен O_NONBLOCK и нет доступных сообщений, он установит errno в EAGAIN или EWOULDBLOCK. O_NONBLOCK не установлен, но MSG_DONTWAIT установлен. Являются ли они в основном тем же, где O_NONBLOCK - для общих файловых дескрипторов, а MSG_DONTWAIT - для сокетов?

Мой мозг сейчас работает не так хорошо, если бы кто-то мог просветить меня и прояснить, в чем заключается мое замешательство, я был бы очень признателен. Спасибо!

Ответы [ 2 ]

14 голосов
/ 04 марта 2010

UDP - это протокол без сохранения состояния, в отличие от TCP, который ориентирован на соединение. Ваш принимающий код не будет знать, закрыл ли отправитель свой сокет, он только знает, есть ли данные, ожидающие чтения. Согласно справочной странице для recvfrom в Linux:

Если в сокете нет доступных сообщений, приемные вызовы ожидают прибытия сообщения, если только сокет не является неблокирующим (см. Fcntl (2)), в этом случае возвращается значение -1 и внешняя переменная errno устанавливается в EAGAIN.

Кажется, это то, что происходит с тобой

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

2 голосов
/ 04 марта 2010

После того, как вы закрыли розетку, она еще некоторое время задерживается.Обычно около двух минут или около того.Чтобы избежать этого, используйте опцию сокета SO_REUSEADDR.

Вот несколько ссылок для вас.

http://msdn.microsoft.com/en-us/library/ms740476%28VS.85%29.aspx http://docs.hp.com/en/B2355-90136/ch03s01.html

А вот пример, прокрутите вниз до функции udp_listen:

http://www.codase.com/search/display?file=L2dlbnRvbzIvdmFyL3RtcC9yZXBvcy9jb2Rhc2UuYy9zbGlycC0xLjAuMTYvd29yay9zbGlycC0xLjAuMTYvc3JjL3VkcC5j&lang=c&off=15730+15796+

...