Будет ли read () когда-либо блокироваться после select ()? - PullRequest
16 голосов
/ 18 марта 2011

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

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

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

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

Ответы [ 5 ]

16 голосов
/ 18 марта 2011

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

Тем не менее, смотрите страницу руководства Linux select :

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

3 голосов
/ 18 марта 2011

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

2 голосов
/ 18 марта 2011

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

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

0 голосов
/ 18 марта 2011

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

0 голосов
/ 18 марта 2011

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

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