2016-10-12 8 views
0

Относительно простой вопрос: когда, скажем, recv() с использованием неблокирующих сокетов Linux, существует ли способ определить априорно, сколько данных доступно для получения?Linux неблокирующие сокеты: сколько данных можно прочитать перед блокировкой?

Кажется, что я всегда собираюсь сделать дополнительный вызов recv(), чтобы определить, что я исчерпал все данные.

+2

Если бы вы могли получить эту информацию, она уже была бы устаревшей, прежде чем вы могли бы воздействовать на нее ... –

+1

Что значит «перед блокировкой»? Это неблокирующий сокет. Он не будет блокироваться. Вы можете просто вызвать 'recv()' до тех пор, пока не произойдет EAGAIN/EWOULDBLOCK. Неясно, что вы спрашиваете. – EJP

ответ

2

Вы можете использовать ioctl() с FIONREAD, чтобы получить количество непрочитанных байтов в буфере сокета.

Однако, это будет также двойной системный вызов, и он все равно не гарантирует, что больше данных не поступит, прежде чем вы вызовете recv().

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

+0

Я уверен, что recv (например, чтение) может предоставить вам столько байтов, сколько сочтет нужным, и что только потому, что он возвращает меньше, чем размер вашего буфера, это не значит, что у него нет данных. – rivenmyst137

+0

@ rivenmyst137: Posix, вероятно, не гарантирует этого, хотя я не видел никакой реализации, которая могла бы вести себя иначе. В любом случае комбинация 'recv()' и 'select()', как описано, будет работать в любом случае. –

0

Вы можете использовать флаг MSG_PEEK в recv, чтобы определить текущее количество байтов для чтения из буфера сокета. Если приложение ожидает определенное количество байтов, прежде чем оно сможет обработать данные, оно может рассчитывать на MSG_PEEK. Данные не будут удалены из буфера сокета. Но ret было бы таким же значением, если бы вы читали без MSG_PEEK.

ret = recv(sd, buf, MAX_CALL_DATA_SIZE, MSG_PEEK);

Этого метод приводит к дополнительным системным вызовам, пока не так много байт требуется приложение находится в буфере сокета. Кроме того, не гарантируется, что к тому времени, когда вы действительно прочитаете данные в приложении, поступит больше байтов.

 Смежные вопросы

  • Нет связанных вопросов^_^