Читайте из сокета

Я должен читать с сокета AF_UNIX на буфер с помощью функции read от C, но я не знаю размер буфера.

Я думаю, что лучший способ состоит в том, чтобы читать N байты до возвратов чтения 0 (больше никаких устройств записи в сокете). Это корректно? Существует ли способ предположить размер буфера, записанного на сокете?

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

Я - очень новое для C, поэтому имейте это в виду.

11
задан jjnguy 16 June 2010 в 13:46
поделиться

5 ответов

Обычно используется ioctl (..) для запроса FIONREAD сокета, который вернет доступный объем данных.

int len = 0;
ioctl(sock, FIONREAD, &len);
if (len > 0) {
  len = read(sock, buffer, len);
}
18
ответ дан 3 December 2019 в 05:11
поделиться

Я думаю, что лучше всего читать N байтов, пока чтение не вернет 0 (нет больше писателей в розетке). Это верный?

0 означает EOF, другая сторона закрыла соединение. Если другая сторона связи закрывает соединение, значит, это правильно.

Если соединение не закрыто (несколько передач по одному и тому же соединению, болтливый протокол), тогда ситуация немного сложнее, и поведение обычно зависит от того, есть ли у вас сокет SOCK_STREAM или SOCK_DGRAM.

Сокеты дейтаграмм уже разграничены для вас ОС.

Потоковые сокеты не разграничивают сообщения (все данные представляют собой непрозрачный поток байтов), и при желании это необходимо реализовать на уровне приложения: например, путем определения поля размера в структуре заголовка сообщения или использования разделителя (например, '\ n 'для однострочных текстовых сообщений). В первом случае вы сначала должны прочитать заголовок, извлечь длину и, используя длину, прочитать остальную часть сообщения. В другом случае считайте поток в частичный буфер, найдите разделитель и извлеките из буфера сообщение, включая разделитель (вам может потребоваться сохранить частичный буфер, поскольку в зависимости от протокола несколько команд могут быть получены с помощью одного recv () / read ( )).

Есть ли способ угадать размер записываемого буфера the socket?

Для потоковых сокетов не существует надежного способа, поскольку другая сторона связи может все еще находиться в процессе записи данных. Представьте себе вполне нормальный случай: буфер сокета 32 КБ, а записывается 128 КБ. Записывающее приложение блокировало бы внутри send () / write (), ОС, ожидая чтения приложения, чтобы прочитать данные и, таким образом, освободить место для следующего фрагмента записанных данных.

Для сокетов дейтаграмм обычно заранее известен размер сообщения. Или можно попробовать (никогда не делал этого сам) recvmsg (MSG_PEEK), и если MSG_TRUNC находится в возвращаемом msghdr.msg_flags, попробуйте увеличить размер буфера.

1
ответ дан 3 December 2019 в 05:11
поделиться

читать N байтов, пока чтение не вернет 0

Да!

Еще одна деталь. Если отправитель не закрывает соединение, сокет просто блокируется, а не возвращается. Неблокирующий сокет вернет -1 (с errno == EAGAIN ), когда нечего читать; это другой случай.

Открытие файла в двоичном режиме и получение размера поможет мне узнать правильный размер для буфера?

Нет. Розетки не имеют размера. Предположим, вы отправили два сообщения по одному и тому же соединению: Каков размер файла?

0
ответ дан 3 December 2019 в 05:11
поделиться

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

1
ответ дан 3 December 2019 в 05:11
поделиться

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

Например,

char buffer[1024];
int ptr = 0;
ssize_t rc;

struct pollfd fd = {
   .fd = sock,
   .events = POLLIN
};

poll(&fd, 1, 0); // Doesn't wait for data to arrive.
while ( fd.revents & POLLIN )
{
   rc = read(sock, buffer + ptr, sizeof(buffer) - ptr);

   if ( rc <= 0 )
      break;

   ptr += rc;
   poll(&fd, 1, 0);
}

printf("Read %d bytes from sock.\n", ptr); 
2
ответ дан 3 December 2019 в 05:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: