C ++ IPC Communication - PullRequest
       21

C ++ IPC Communication

1 голос
/ 22 февраля 2012

Я в затруднительном положении, чтобы принять решение по нижеприведенным сценариям. Пожалуйста, нуждайтесь в помощи экспертов.

Сценарий: TCP / IP-связь между двумя процессами, запущенными в двух блоках.

Способ связи 1: Потоковая связь через сокет. На стороне получателя он получит весь байтовый буфер и интерпретирует первые несколько фиксированных байтов как заголовок, десериализует его, узнает длину сообщения и начинает принимать сообщение этой длины, десериализует его и переходит к следующему заголовку сообщения, как это происходит на ....

Способ связи2: Поместите все сообщения в вектор, а вектор будет находиться в объекте класса. сериализовать объект класса за один раз и отправить получателю. Приемник десериализует объект класса и читает массив векторов один за другим.

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

Кроме того, плюсы и минусы передачи данных на основе классов и передачи данных на основе структур и какой из них подходит для какого сценария?

Ответы [ 4 ]

5 голосов
/ 22 февраля 2012

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

В частности, метод 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 ++.

0 голосов
/ 22 февраля 2012

Если это не домашнее задание или учебный проект, может быть мало смысла возиться с IPC на уровне потока TCP, особенно если это не то, с чем каждый знаком.

Используйте библиотеку сообщений, такую ​​как ØMQ , чтобы отправлять и получать полные сообщения, а не потоки байтов.

0 голосов
/ 22 февраля 2012

Имейте в виду, что не безопасно - просто выводить структуру или класс напрямую, интерпретируя его как последовательность байтов, даже если это простой POD - есть проблемы, такие как endianness (что вряд лиреальная проблема для большинства из нас) и выравнивание / заполнение структуры (что является потенциальной проблемой).

C ++ не имеет встроенной сериализации / десериализации, выВам придется либо бросить свой собственный, либо взглянуть на такие вещи, как boost Serialization или Google protobuf .

0 голосов
/ 22 февраля 2012

Оба метода эквивалентны. В обоих случаях вы должны отправить заголовок с размером сообщения и идентификатором для десериализации. Если вы предполагаете, что первый вариант составлен сериализованным «классом», как обычное сообщение, вы должны реализовать тот же «код».

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

...