Может ли msgpack упаковать пользовательский объект в С#, отправить пакет в приложение на С++, где он затем распаковывается?

У меня есть сервер ответов С#, который может упаковать объект и отправить его запрашивающему клиенту С#. Могу ли я сделать то же самое, но с сервером ответов C#, взаимодействующим с запрашивающим клиентом C++?

Вот пример моего сервера ответов C#:

using System;
using System.Text;
using ZMQ;
using MsgPack;

namespace zmqMpRep
{
    public class Weather
    {
        public int zipcode;
        public int temperature;
        public int humidity;
    }
    public class zmqMpRep
    {
        public static void Main(string[] args)
        {

            Socket replier  = new Socket( SocketType.REP );
            replier.Bind( "tcp://127.0.0.1:9293" );
            while( true ) {
                Weather weather = new Weather { zipcode = 60645, temperature = 67, humidity = 50 };
                CompiledPacker packer   = new CompiledPacker( false );
                byte[] packWeather  = packer.Pack<Weather> ( weather );
                string request  = replier.Recv(Encoding.Unicode);
                Console.WriteLine( request.ToString() );
                replier.Send( packWeather );
                Weather test    = packer.Unpack<Weather>( packWeather );
                Console.WriteLine( "The temp of zip {0} is {1}", test.zipcode, test.temperature );
            }
        }
    }
}

Вот мой клиент запросов С#:

using System;
using System.Text;
using ZMQ;
using MsgPack;

namespace zmqMpReq
{
    public class Weather
    {
        public int zipcode;
        public int temperature;
        public int humidity;
    }
    public class zmqMpReq
    {
        public static void Main(string[] args)
        {
            CompiledPacker packer   = new CompiledPacker( false );
            Socket requester        = new Socket( SocketType.REQ );
            requester.Connect( "tcp://127.0.0.1:9293" );
            string request          = "Hello";
            requester.Send( request, Encoding.Unicode );
            byte[] reply            = null;
            try {
                reply        = requester.Recv();
            }
            catch( ZMQ.Exception e) {
                Console.WriteLine( "Exception: {0}", e.Message );
            }
            Weather weather     = packer.Unpack<Weather>( reply );
            Console.WriteLine( "The temp of zip {0} is {1}", weather.zipcode, weather.temperature );
            System.Threading.Thread.Sleep( 5000 );
        }
    }
}

person EhevuTov    schedule 09.11.2011    source источник


Ответы (2)


Большинство программ, написанных на любом языке, могут обмениваться данными через сокеты. Таким образом, прослушиватель сокета C# может прослушивать отправителя C++. Они делают это путем обмена последовательностью байтов (очень упрощенно)

Здесь вы сериализуете объект C# с помощью MsgPack в массиве байтов и отправляете его. На другом конце тот же MsgPack используется для десериализации объекта C#.

Это не будет работать на разных языках программирования, если ваша библиотека сериализации/десериализации не поддерживает это, что в вашем случае MsgPack не поддерживает.

Возьмите этот класс С#

public class Weather
{
    public int zipcode;
    public int temperature;
    public int humidity;
}

Эквивалентный класс C++

  class Weather
    {
    public:
       int zipcode;
       int temperature;
       int humidity;
    }

В зависимости от вашей ОС. sizeof(int) в С++ будет 4 байта (символы). sizeof(int) в С# также равен 4 байтам.

Таким образом, теоретически вы можете обмениваться 12 ( 4 * 3 ) байтами через сокетное соединение между программой C++ и C#, чтобы объект погоды был практически одинаковым с обеих сторон.

person parapura rajkumar    schedule 10.11.2011
comment
Можете ли вы порекомендовать какую-либо (де) сериализующую библиотеку, которая не зависит от языка? - person EhevuTov; 10.11.2011
comment
stackoverflow.com/questions/144435/ содержит все ответы - person parapura rajkumar; 10.11.2011
comment
Твои примеры тоже о том, о чем я думаю. Я полагаю, что на свободно типизированном языке было бы сложнее заставить правильный размер байта, но, я думаю, он также работал бы. Messagepack говорит, что он создан для структурированных данных между несколькими языками, но я не вижу никакой схемы для обозначения фактической структуры, например файла ASN.1 для чего-то. Это немного открыто. - person EhevuTov; 10.11.2011
comment
На самом деле, похоже, что у Message Pack есть IDL, но он еще не очень хорошо поддерживается. - person EhevuTov; 10.11.2011
comment
Рассматривали ли вы что-то более высокого уровня, например WCF. Родной WCF - person parapura rajkumar; 10.11.2011
comment
Нет, нет. Я ищу более открытое решение. - person EhevuTov; 11.11.2011

В C++ вы должны использовать макрос MSGPACK_DEFINE, потому что вы имеете дело с классом, определяемым пользователем. Все это объясняется в кратком руководстве по C++ на веб-сайте MSGPACK.

Чтобы это работало, вы должны убедиться, что типы каждого атрибута в вашем объекте соответствуют языкам. Это именно то, для чего был предназначен MSGPACK, и я сам использовал его для написания сервера SQLITE на основе сообщений ZeroMQ, содержащих полезную нагрузку объекта MSGPACK. Первоначально я использовал объект JSON для тел сообщений, но затем мне захотелось отправить один атрибут в формате gzip, и было проще поменять местами в MSGPACK, чем пытаться работать с двоичными данными в строке JSON.

Вы можете прочитать http://wiki.msgpack.org/display/MSGPACK/Design+of+Serialization, чтобы понять, как это работает. Концептуально это похоже на преобразование 000A00130002 в «10,19,2» и обратно. Конечно, MSGPACK не использует строки в качестве формата сериализации, а вместо этого использует очень эффективный двоичный формат, не зависящий от языка.

person Michael Dillon    schedule 11.11.2011
comment
Спасибо. Знаете ли вы, существует ли компилятор IDL для C# и C++? Msgpack говорит о том, что он независим от языка, но пока похоже, что мне все еще приходится вручную структурировать используемые языки. - person EhevuTov; 11.11.2011
comment
Существует экспериментальный IDL, написанный на Ruby, но в настоящее время я думаю, что он генерирует только вывод Java. IDL действительно нужен только в том случае, если вы делаете МНОГО разных типов сообщений. - person Michael Dillon; 12.11.2011