4

I have a C# reply server that can pack an object and send it to a requester C# client. Can I do the same thing, but with a C# reply server communicating with a C++ requester client?

Here's an example of my C# reply server:

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 );
            }
        }
    }
}

Here's my C# request client:

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 );
        }
    }
}
EhevuTov
  • 20,205
  • 16
  • 66
  • 71

2 Answers2

3

Most programs written in any language can communicate over sockets. So a C# socket listener can listen to C++ sender. They do by exchanging a sequence of bytes (Very simplified)

What you are doing here is serializing a C# object using MsgPack in a byte array and sending it over. On the other end the same MsgPack is used to deserialize the C# object.

This will not work across programming languages unless your serializing/deserializing library supports it, which in your case MsgPack doesn't.

Take this C# class

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

An equivalent C++ class

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

Depending on your OS.. sizeof(int) in C++ will be 4 bytes(chars). sizeof(int) in C# is 4 bytes as well.

So it theory you can exchange 12 ( 4 * 3 ) bytes over a socket connection between a C++ and C# program so that weather object is pretty much the same on both sides

parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85
  • 1
    Can you recommend any (de)serializing library that is language agnostic? – EhevuTov Nov 10 '11 at 00:30
  • http://stackoverflow.com/questions/144435/whats-the-best-way-to-serialize-data-in-a-language-independent-binary-format has all the answers – parapura rajkumar Nov 10 '11 at 00:35
  • Your examples are of what I'm thinking as well. I loosely-typed language, I imagine, would be harder to coerce the correct byte size, but would also work, I would think. Messagepack says that it's built for structured data between multiple languages, but I don't see any schema to denote the actual structure, like an ASN.1 file for something. It's a bit open-ended. – EhevuTov Nov 10 '11 at 02:16
  • 1
    Actually, it looks like Message Pack does have an IDL, but it's not supported very much yet. – EhevuTov Nov 10 '11 at 02:24
  • Have you considered something higher level like WCF. [Native WCF](http://blogs.msdn.com/b/nikolad/archive/2009/03/03/demo-of-wwsapi-from-mvp-summit.aspx) – parapura rajkumar Nov 10 '11 at 02:26
  • No I haven't. I'm looking for a more open solution. – EhevuTov Nov 11 '11 at 15:03
1

In C++ you should use the MSGPACK_DEFINE macro because you are dealing with a user-defines class. It is all explained in the C++ quickstart on the MSGPACK website.

In order for this to work you have to make sure that the types of each attribute in your object corresponds across languages. This is exactly what MSGPACK was intended to do and I have used it myself to write an SQLITE server based on ZeroMQ messages containing a MSGPACK object payload. Originally I was using a JSON object for the message bodies but then I wanted to send one attribute in gzipped form and it was easier to swap in MSGPACK than try to deal with binary data in a JSON string.

You might want to read http://wiki.msgpack.org/display/MSGPACK/Design+of+Serialization to understand how it works. Conceptually it is like converting 000A00130002 into "10,19,2" and back again. Of course, MSGPACK doesn't use strings as the serialization format but instead uses a very efficient binary format that is language independent.

Michael Dillon
  • 31,973
  • 6
  • 70
  • 106
  • Thank you. Do you know if there is an IDL compiler for C# and C++? Msgpack talks about being language agnostic, but so far it looks like I still have to do the structuring manually in the used languages. – EhevuTov Nov 11 '11 at 08:07
  • There is an experimental IDL written in Ruby but at present I think that it only generates Java output. An IDL is really only needed if you are doing a LOT of different message types. – Michael Dillon Nov 11 '11 at 22:31