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

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

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

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

4b9b3361

Ответ 1

Да:

#include <sys/ioctl.h>

...

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

Это "вид" ответа: recv(char* buffer, size_t nytes, int flags), где флаги OR'ed:

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

Ответ 6

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

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