Подтвердить что ты не робот

Будет ли() когда-либо блокироваться после select()?

Я читаю поток данных через сокет TCP/IP. Нагрузка потока очень неравномерна. Иногда большие объемы данных поступают каждую секунду, иногда данные не поступают в течение часа. В случае длительного периода бездействия (никаких данных с удаленного сервера, но соединение все еще в сети) моя программа должна предпринять некоторые действия.

Я использую тайм-аут, используя select(). Это говорит мне, есть ли готовые данные, но я точно не знаю, сколько я могу прочитать, не вызывая блокировку read(). Блокировка неприемлема, поскольку она может длиться намного дольше, чем требуемый тайм-аут.

Для эффективности поток считывается в большой буфер, а вызов read() предоставляется с этим размером буфера.

Будет ли блок read() после select(), если заполняемый буфер больше, чем объем данных, доступных прямо сейчас в сокете?

4b9b3361

Ответ 1

На самом деле он не должен блокироваться (это то, что select() для!), но на самом деле он может, в исключительных случаях. Обычно read() должен возвращать до максимального количества байт, которые вы указали, что может включать в себя нулевые байты (на самом деле это действительно так!), Но он никогда не должен блокироваться после того, как ранее сообщалось о готовности.

Тем не менее, см. справочную страницу Linux select:

В Linux, select() может сообщить дескриптор файла сокета как "готовый для чтение", хотя, тем не менее, последующие блоки чтения. Это могло, это может например, когда данные имеют прибыл, но на экзамене контрольной суммы и отбрасывается. Может быть другими обстоятельствами, в которых файл дескриптор ложно сообщается как готов. Таким образом, может быть безопаснее использовать O_NONBLOCK на сокетах, которые не должны блок.

Ответ 2

Существует O_NONBLOCK, который может быть установлен fcntl/F_SETFL и должен привести к неблокированию read.

Ответ 3

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

Итак, у вас есть две отдельные проблемы. (1) Вы хотите "предпринять какие-то действия", когда данных нет. Это время ожидания выбора. (2) Как только у вас есть данные (уведомлены по выбору), вы не хотите блокировать чтение. Это неблокирующий режим. Когда вы получаете EAGAIN на неблокируемом чтении, вы возвращаетесь к выбору и/или "выполняете некоторые действия" и выбираете цикл назад.

Ответ 4

Нет, read() будет считывать указанный размер и будет возвращать фактические байты, которые могут быть меньше.

Ответ 5

Вы можете использовать recv(), который не блокируется по умолчанию (если флаг MSG_WAITALL не указан)