Насколько большим должен быть мой буфер recv при вызове recv в библиотеке сокетов

077 = 7 * 8 ^ 0 + 7 * 8 ^ 1 = 63; 0123 = 3 * 8 ^ 0 + 2 * 8 ^ 1 + 1 * 8 ^ 2 = 3 + 16 + 64 = 83; Первое значение 0 означает восьмеричное значение.

0x77 - это hex val.

125
задан Chen XinZhen 19 September 2015 в 08:32
поделиться

5 ответов

Ответы на эти вопросы зависят от того, используете ли вы сокет потока ( SOCK_STREAM ) или сокет дейтаграммы ( SOCK_DGRAM ) - в рамках TCP / IP, первый соответствует TCP, а второй - UDP.

Как узнать размер буфера, передаваемого в recv () ?

  • SOCK_STREAM : На самом деле это не имеет большого значения.Если ваш протокол является транзакционным / интерактивным, просто выберите размер, который может содержать наибольшее отдельное сообщение / команду, которых вы могли бы разумно ожидать (3000, вероятно, в порядке). Если ваш протокол передает большие объемы данных, то буферы большего размера могут быть более эффективными - хорошее практическое правило примерно такое же, как размер приемного буфера ядра сокета (часто около 256 КБ).

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

Что произойдет, если recv получит пакет больше, чем размер буфера?

  • SOCK_STREAM : вопрос не имеет смысла в том виде, в каком он поставлен, поскольку в потоковых сокетах отсутствует концепция пакеты - это просто непрерывный поток байтов. Если доступно для чтения больше байтов, чем имеется место в вашем буфере, они будут помещены в очередь ОС и доступны для вашего следующего вызова recv .

  • SOCK_DGRAM : лишние байты отбрасываются.

Как я могу узнать, получил ли я все сообщение?

  • SOCK_STREAM : Вам нужно встроить какой-то способ определения конца сообщения в протокол уровня приложения. Обычно это либо префикс длины (начало каждого сообщения с длины сообщения), либо разделитель конца сообщения (который может быть, например, просто новой строкой в ​​текстовом протоколе).Третий, менее используемый вариант - установить фиксированный размер для каждого сообщения. Также возможны комбинации этих параметров - например, заголовок фиксированного размера, который включает значение длины.

  • SOCK_DGRAM :Один вызов recv всегда возвращает одну дейтаграмму.

Есть ли способ сделать буфер не имеющим фиксированного количества места, чтобы я мог продолжать добавлять его, не опасаясь нехватки места?

Нет. Однако вы можете попробовать изменить размер буфера с помощью realloc () (если он был изначально выделен с помощью malloc () или calloc () , то есть).

223
ответ дан 24 November 2019 в 00:52
поделиться

Если у вас сокет SOCK_STREAM, recv просто получит "до первых 3000 байт" из потока. Нет четкого руководства о том, какого размера делать буфер: единственный раз, когда вы знаете, насколько велик поток, это когда все готово;-).

Если у вас есть сокет SOCK_DGRAM, и датаграмма больше буфера, recv заполняет буфер первой частью датаграммы, возвращает -1 и устанавливает errno в EMSGSIZE. К сожалению, если протокол UDP, это означает, что остальная часть дейтаграммы будет потеряна - часть того, почему UDP называют ненадежным протоколом (я знаю, что существуют надежные дейтаграммные протоколы, но они не очень популярны - я не смог назвать ни одного из семейства TCP/IP, хотя знаю последний довольно хорошо;-).

Чтобы динамически увеличивать буфер, выделите его изначально с помощью malloc и используйте realloc по мере необходимости. Но это, увы, не поможет вам при recv от источника UDP.

15
ответ дан 24 November 2019 в 00:52
поделиться

Для потоковых протоколов, таких как TCP, вы можете установить любой размер буфера. Тем не менее, рекомендуются обычные значения, равные степени 2, такие как 4096 или 8192.

Если данных будет больше, чем в буфере, они будут просто сохранены в ядре для следующего вызова recv.

Да, вы можете продолжать увеличивать свой буфер. Вы можете сделать recv в середину буфера, начиная со смещения idx, вы сделаете:

recv(socket, recv_buffer + idx, recv_buffer_size - idx, 0);
16
ответ дан 24 November 2019 в 00:52
поделиться

16кб примерно правильно; если вы используете гигабитный Ethernet, размер каждого пакета может составлять 9 КБ.

-4
ответ дан 24 November 2019 в 00:52
поделиться

На ваш вопрос нет однозначного ответа, потому что технология всегда зависит от реализации. Я предполагаю, что вы общаетесь по UDP, потому что размер входящего буфера не создает проблем для TCP-связи.

Согласно RFC 768 размер пакета (включая заголовок) для UDP может составлять от 8 до 65 515 байтов. Таким образом, безотказный размер входящего буфера составляет 65 507 байтов (~ 64 КБ)

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

Каков оптимальный размер пакета UDP для максимальной пропускной способности?
Каков самый большой размер безопасного пакета UDP в Интернете

1
ответ дан 24 November 2019 в 00:52
поделиться
Другие вопросы по тегам:

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