Предоставляет ли libuv какие-либо средства для подключения буфера к соединению и его повторного использования?

Я оцениваю libuv как библиотеку для сервера C/С++, который я пишу. Протокол имеет префикс длины, поэтому, как только я смогу прочитать 32-битное целое число из потока, я смогу определить, какой размер буфера я должен выделить. В документации сказано, что функция uv_read_start может вызываться несколько раз.

UV_EXTERN int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);

Поскольку я использую протокол с префиксом длины, как только я узнаю правильный размер буфера, я хотел бы выделить его и повторно использовать для последующих чтений, пока не получу все свои байты. Есть ли простой способ сделать это с помощью libuv? Сейчас кажется, что об этом должна позаботиться функция uv_alloc_cb. Могу ли я связать буфер с моим потоковым объектом вместо того, чтобы помещать его на карту или что-то в этом роде?

Поскольку я использую протокол с префиксом длины, я бы вообще не хотел выделять буфер в куче, пока не смогу прочитать первые 4 байта (32 бита). Могу ли я выделить в стеке буфер размером 4 и заставить функцию uv_read_cb фактически выполнять выделение кучи? Вызывается ли функция uv_read_cb синхронно как часть функции uv_read_start? Если это так, то кажется, что я должен иметь возможность выделять в стеке, когда я знаю, что у меня еще нет буфера, прикрепленного к моему потоку.


person Rajiv    schedule 07.10.2013    source источник
comment
stackoverflow .com/questions/41000029/   -  person Bernardo Ramos    schedule 07.12.2016


Ответы (1)


Отвечая на мой собственный вопрос. Я нашел ответы в списке рассылки libuv здесь: https://groups.google.com/forum/#!topic/libuv/fRNQV_QGgaA

Скопируйте данные сюда, если ссылка станет недоступной:

Присоединение собственной структуры данных к дескриптору:

В дескрипторе есть поле void* data, которое вы можете использовать. Вы можете указать ему вспомогательную структуру, где вы храните длину и буфер.

В качестве альтернативы вы можете внедрить uv_tcp_t в другую структуру, а затем найти структуру внедрения с помощью container_of. Это не стандартный макрос C, но вы можете найти его определение и примеры использования в дереве libuv/source. Его преимущество в том, что он просто выполняет некоторые арифметические операции с указателями, что избавляет вас от другого уровня косвенного обращения с указателями.

Выделение стека для буфера приема:

Нет, это невозможно. Правильный способ думать об этом состоит в том, что ваш alloc_cb возвращает буфер, который libuv заполнит данными когда-нибудь в будущем. Акцент делается на «когда-нибудь», потому что нет никаких гарантий, когда это произойдет; это может быть немедленно, это может быть через секунды (или минуты).

person Rajiv    schedule 07.10.2013