В вашем вопросе отсутствуют некоторые ключевые детали, и в нем сочетаются различные проблемы, что сводит на нет все попытки дать хороший ответ.
В частности, метод 2 таинственно «сериализует» и «десериализует» объект и содержит вектор без указания какого-либо вектора.детали того, как это делается.На практике детали такого рода упоминаются в методе 1. Итак, 1 и 2 не являются альтернативами, если вы не выбираете между использованием библиотеки сериализации и выполнением ее с нуля (в этом случае я бы сказал, использовать библиотекупоскольку вы новичок в этом, и у библиотеки, скорее всего, все получится правильно).
Что я могу сказать:
- на уровне TCP, наиболее эффективно читать вблок приличного размера (учитывая, что я склонен работать на оборудовании ПК / сервера, я бы просто использовал 64 КБ, хотя меньшего может быть достаточно для получения одинаковой пропускной способности), и каждый
read()
или recv()
считывал столько данных изСокет максимально возможный - после чтения достаточного количества байтов (хотя и большого числа операций чтения / записи), чтобы попытаться интерпретировать данные, необходимо распознать конец отдельных частей сериализованного ввода: иногда это неявно присутствует в типе данныхучаствует, в других случаях он сообщается с использованием некоторого сторожа (например, перевода строки или NUL), а в других случаях может существовать префикс фиксированного размера «ожидаемый N байт»s "заголовок.Этот аспект / соображение часто применяется иерархически к потоку объектов и вложенных подобъектов и т. Д.
- чтение / запись TCP может доставить больше данных, чем было отправлено в любом отдельном запросе, поэтому у вас может быть 1 или более байтовкоторые логически являются частью последующего, но неполного логического сообщения в конце блока, собранного выше
- , процесс чтения больших блоков с последующим доступом к различным элементам фиксированного и переменного размера внутри буферов уже поддерживается iostreams C ++, ноВы можете свернуть свой собственный, если хотите
Итак, позвольте мне подчеркнуть это: НЕ ДОПУСКАЙТЕ, что вы получите более 1 байта от любого данного чтения сокета: есливы сказали 20-байтовый заголовок, который вы должны читать в цикле, пока не получите ошибку или не соберете все 20 байтов.Отправка 20 байтов в одном write()
или send()
не означает, что 20 байтов будут представлены одному read()
/ recv()
.TCP является протоколом потока байтов, и вы должны принимать произвольное количество байтов, как и когда они предоставляются, ожидая, пока у вас не будет достаточно данных для их интерпретации.Точно так же будьте готовы получить больше данных, чем клиент мог бы записать в одном write()
/ `send ().
Также плюсы и минусы передачи данных на основе классов и передачи данных на основе структуры и которыедля какого сценария подходит?
Эти термины полностью фиктивны.классы и структуры в C ++ почти идентичны - механизмы группировки данных и связанных функций (они отличаются только тем, как они - по умолчанию - предоставляют базовые классы и члены данных клиентскому коду).Либо может иметь, либо не иметь функции-члены или код поддержки, который помогает сериализовать и десериализовать данные.Например, самой простой и типичной поддержкой являются функции потоковой передачи operator<<
и / или operator>>
.
Если вы хотите противопоставить потоковые функции такого типа специальному подходу «напишите двоичный блок, прочитайте двоичный блок» (возможно, исходя из представления о структурах как о POD без кода поддержки), то я бы сказал, что предпочтет потоковые функции, где это возможно, начиная с потоковой передачи до понятных человеку представлений, поскольку они облегчат и упростят разработку, отладку и поддержку вашей системы. Как только вы действительно освоитесь с этим, если производительность во время выполнения этого требует, оптимизируйте ее с помощью двоичного представления. Если вы хорошо написали код сериализации, вы не заметите большой разницы в производительности между более грубой моделью данных void*/#bytes
и правильной сериализацией для каждого члена, но последняя может легче поддерживать необычные случаи - переносимость между системами с разным размером целых / longs и т. д., различное упорядочение байтов, преднамеренный выбор или неглубокое копирование указанных данных и т. д ....
Я бы также порекомендовал взглянуть на библиотеку Boost-сериализации. Даже если вы его не используете, это должно дать вам лучшее понимание того, как подобные вещи разумно реализованы в C ++.