问题
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 );
}
}
}
回答1:
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
回答2:
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.
来源:https://stackoverflow.com/questions/8072953/can-msgpack-pack-a-user-defined-object-in-c-send-the-pack-to-a-c-app-where-i