it-roy-ru.com

Как проверить количество данных, доступных для сокета в C и Linux

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

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

28
Jimm

Да:

#include <sys/ioctl.h>

...

int count;
ioctl(fd, FIONREAD, &count);
50
fizzer

Нет, нет Даже если бы был способ сделать это, любой полученный вами ответ был бы немедленно устаревшим (потому что новые данные могут поступить в любое время).

Обратите внимание, что когда вы передаете буфер в read(), функция вернется, когда будет любой объем данных для чтения (по крайней мере, один байт), вместо ожидания полного заполнения буфера.

4
Greg Hewgill

Это «своего рода» ответ: recv(char* buffer, size_t nytes, int flags) где flags это OR с:

MSG_PEEK
This flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue. Thus, a subsequent receive call will return the same data.

Таким образом, вы можете увидеть, существует ли в буфере произвольное количество байтов, без необратимого чтения буфера. Это неполный ответ, потому что это не самый эффективный способ сделать это, и MSG_PEEK обычно используется, когда сообщения имеют заголовки известной длины, например, так:

000123DT001    

где 00123 - длина всего сообщения, включая заголовок, DT - тип сообщения, а 001 - количество попыток отправителя. Идея состоит в том, что вы можете извлечь что-то, что скажет вам, сколько байтов полностью прочитало сообщение. Вы не заинтересованы в сообщениях. Но это причина MSG_PEEK

2
jim mcnamara

Вы должны попытаться отправить и получить команду, а также вы можете читать и записывать в сокет символ за символом, чтобы не тратить память и еще лучше общаться.

2
ravi bhuva

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

1
yeyo

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

поэтому вы можете попробовать интерфейсы сокетов PACKET для ядер Linux 2.4 или 2.6+ попробуйте это http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txt

0
akp