Быстрое межплатформенное межпроцессное взаимодействие в C ++ - PullRequest
19 голосов
/ 08 февраля 2010

Я ищу способ заставить две программы эффективно передавать друг другу большое количество данных, которые должны работать в Linux и Windows, в C ++. Контекст здесь - это сетевая программа P2P, которая действует как узел в сети и работает непрерывно, и другие приложения (которые могут быть играми, отсюда необходимость быстрого решения) будут использовать это для связи с другими узлами в сети. Если есть лучшее решение для этого, мне было бы интересно.

Ответы [ 6 ]

15 голосов
/ 08 февраля 2010

boost :: asio - кроссплатформенная библиотека, обрабатывающая асинхронный ввод-вывод через сокеты. Вы можете комбинировать это с использованием, например, буферов протокола Google для ваших реальных сообщений.

Boost также предоставляет вам boost :: interprocess для межпроцессного взаимодействия на одной и той же машине, но asio позволяет выполнять асинхронное взаимодействие, и вы можете легко иметь одинаковые обработчики как для локальных, так и для удаленных соединений.

6 голосов
/ 08 февраля 2010

Я использовал ICE от ZeroC ( www.zeroc.com ), и это было потрясающе. Супер прост в использовании, и он не только кроссплатформенный, но также поддерживает многие языки (Python, Java и т. Д.) И даже встроенную версию библиотеки.

3 голосов
/ 08 февраля 2010

Что ж, если мы можем предположить, что два процесса выполняются на одной машине, то самый быстрый способ передачи больших объемов данных туда и обратно - это хранение данных в общей области памяти; при такой настройке данные никогда не копируются вообще, так как оба процесса могут получить к ним доступ напрямую. (Если вы хотите пойти еще дальше, вы можете объединить две программы в одну программу, при этом каждый прежний «процесс» теперь будет выполняться как поток внутри одного и того же пространства процессов. В этом случае они будут автоматически распределять 100% своей памяти друг с другом)

Конечно, просто иметь общую область памяти в большинстве случаев недостаточно: вам также понадобится какой-то механизм синхронизации, чтобы процессы могли безопасно читать и обновлять общие данные, не прерывая работу друг друга. Я бы сделал так, чтобы создать две двусторонние очереди в области общей памяти (по одной на каждый процесс для отправки). Либо используйте класс FIFO-очереди без блокировки, либо присвойте каждой двусторонней очереди семафор / мьютекс, который можно использовать для сериализации, помещая элементы данных в очередь и выталкивая элементы данных из очереди. (Обратите внимание, что элементы данных, которые вы будете помещать в очереди, будут только указателями на фактические буферы данных, а не на сами данные ... в противном случае вы вернетесь к копированию больших объемов данных, которых вы хотите избежать Хорошая идея - использовать shared_ptrs вместо простых указателей на Си, чтобы «старые» данные автоматически освобождались, когда процесс получения завершил их использование). Когда у вас есть это, единственное, что вам нужно, - это способ для процесса A уведомить процесс B, когда он только что поместил элемент в очередь для получения B (и наоборот) ... Обычно я делаю это запись байта в канал, который выбирает другой процесс (), чтобы заставить другой процесс проснуться и проверить свою очередь, но есть и другие способы сделать это.

1 голос
/ 08 февраля 2010

Я настоятельно рекомендую Буферы протокола поверх сокетов TCP или UDP.

1 голос
/ 08 февраля 2010

Это сложная проблема.

Узким местом является Интернет, и ваши клиенты могут использовать NAT.

Если вы не разговариваете по Интернету, или если у вас явно нет клиентов за злыми NATами операторского уровня, вам нужно сказать.

Потому что это сводится к: использовать TCP. Смирись.

0 голосов
/ 08 февраля 2010

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

Во-первых, библиотека ICE здесь - это метод обхода NAT, который работает с серверами STUN и / или TURN в сети. Возможно, вам придется предоставить некоторую инфраструктуру, чтобы это работало, хотя есть некоторые общедоступные серверы STUN.

Во-вторых, используйте UPnP и NAT-PMP. Одна библиотека здесь , например.

В-третьих, используйте IPv6. Teredo, который является одним из способов запуска IPv6 поверх IPv4, часто работает, когда ничего из перечисленного не работает, и кто знает, что ваши пользователи могут использовать IPv6 другими способами. Очень мало кода для реализации этого, и это становится все более важным. Я считаю, что около половины данных Bittorrent поступает, например, по IPv6.

...