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.
Ответы на эти вопросы зависят от того, используете ли вы сокет потока ( 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 ()
, то есть).
Если у вас сокет SOCK_STREAM
, recv
просто получит "до первых 3000 байт" из потока. Нет четкого руководства о том, какого размера делать буфер: единственный раз, когда вы знаете, насколько велик поток, это когда все готово;-).
Если у вас есть сокет SOCK_DGRAM
, и датаграмма больше буфера, recv
заполняет буфер первой частью датаграммы, возвращает -1 и устанавливает errno в EMSGSIZE. К сожалению, если протокол UDP, это означает, что остальная часть дейтаграммы будет потеряна - часть того, почему UDP называют ненадежным протоколом (я знаю, что существуют надежные дейтаграммные протоколы, но они не очень популярны - я не смог назвать ни одного из семейства TCP/IP, хотя знаю последний довольно хорошо;-).
Чтобы динамически увеличивать буфер, выделите его изначально с помощью malloc
и используйте realloc
по мере необходимости. Но это, увы, не поможет вам при recv
от источника UDP.
Для потоковых протоколов, таких как TCP, вы можете установить любой размер буфера. Тем не менее, рекомендуются обычные значения, равные степени 2, такие как 4096 или 8192.
Если данных будет больше, чем в буфере, они будут просто сохранены в ядре для следующего вызова recv
.
Да, вы можете продолжать увеличивать свой буфер. Вы можете сделать recv в середину буфера, начиная со смещения idx
, вы сделаете:
recv(socket, recv_buffer + idx, recv_buffer_size - idx, 0);
16кб примерно правильно; если вы используете гигабитный Ethernet, размер каждого пакета может составлять 9 КБ.
На ваш вопрос нет однозначного ответа, потому что технология всегда зависит от реализации. Я предполагаю, что вы общаетесь по UDP, потому что размер входящего буфера не создает проблем для TCP-связи.
Согласно RFC 768 размер пакета (включая заголовок) для UDP может составлять от 8 до 65 515 байтов. Таким образом, безотказный размер входящего буфера составляет 65 507 байтов (~ 64 КБ)
Однако не все большие пакеты могут быть правильно маршрутизированы сетевыми устройствами, обратитесь к существующему обсуждению для получения дополнительной информации:
Каков оптимальный размер пакета UDP для максимальной пропускной способности?
Каков самый большой размер безопасного пакета UDP в Интернете