select (), recv () и EWOULDBLOCK для неблокирующих сокетов - PullRequest
9 голосов
/ 26 мая 2009

Хотелось бы узнать, реальн ли следующий сценарий?!

  1. select () (RD) для неблокирующего сокета TCP говорит, что сокет готов
  2. после recv () вернет EWOULDBLOCK, несмотря на вызов select ()

Ответы [ 8 ]

4 голосов
/ 26 мая 2009

Для recv() вы получите EAGAIN вместо EWOULDBLOCK, и да, это возможно. Поскольку вы только что проверили с select(), произошла одна из двух вещей:

  • Что-то еще (другой поток) опустошило входной буфер между select() и recv().
  • Тайм-аут приема был установлен на сокете, и он истек без получения данных.
3 голосов
/ 23 августа 2009

В Linux даже задокументировано, что это может произойти, как я читал.

Смотрите этот вопрос:

Уведомление о ложной готовности для системного вызова Select

3 голосов
/ 27 мая 2009

Мне известно об ошибке в популярном рабочем столе, когда O_NONBLOCK TCP-сокеты, особенно те, которые работают через интерфейс обратной связи, иногда могут возвращать EAGAIN из recv() после того, как select() сообщает, что сокет готов для чтения , В моем случае это происходит после того, как другая сторона наполовину закрывает поток отправки.

Для получения дополнительной информации см. Исходный код для t_nx.ml в библиотеке NX моего дистрибутива OCaml Network Application Environment. ( ссылка )

1 голос
/ 26 мая 2009

Это возможно, но только в ситуации, когда у вас есть несколько потоков / процессов, пытающихся читать из одного сокета.

0 голосов
/ 21 февраля 2019

Да, это реально. Вот как это может произойти:

Будущая модификация протокола TCP добавляет возможность для одной стороны «отзывать» информацию, которую она отправила, при условии, что она еще не была получена прикладным уровнем другой стороны. Эта функция согласовывается при подключении. Другая сторона отправляет вам некоторые данные, вы получаете удар select. Прежде чем вы сможете вызвать recv, другая сторона «аннулирует» данные, используя это новое расширение. Ваш read получает сообщение об ошибке "блокирует", потому что нет доступных данных для чтения.

Функция select - это функция сообщения о состоянии, которая не сопровождается будущими гарантиями. Предполагая, что нажатие на select теперь гарантирует, что последующая операция не будет блокирована, столь же недействительно, как и использование любой другой функции сообщения о состоянии таким образом. Это так же плохо, как использовать access, чтобы попытаться гарантировать, что последующая операция не завершится с ошибкой из-за неправильных разрешений, или использовать statfs, чтобы попытаться гарантировать, что последующая запись не завершится с ошибкой из-за заполнения диска.

0 голосов
/ 27 мая 2009

Хотя мое приложение является однопоточным, я заметил, что описанное поведение не редкость в RHEL5. Оба с сокетами TCP и UDP, которые были установлены в O_NONBLOCK (единственный параметр сокета, который установлен). select () сообщает, что сокет готов, но следующая функция recv () возвращает EAGAIN.

0 голосов
/ 26 мая 2009

Если вы не вызываете какой-либо другой системный вызов между select () и recv () в этом сокете, то recv () никогда не вернет EAGAIN или EWOULDBLOCK.

Я не знаю, что они имеют в виду под recv-timeout, однако стандарт POSIX здесь не упоминает об этом, так что вы можете безопасно вызывать recv ().

0 голосов
/ 26 мая 2009

Это возможно в многопоточной среде, где два потока читают из сокета. Это многопоточное приложение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...