序列化 Protobuf 对象并使用 ØMQ/ZMQ 发送
Serializing Protobuf Object and Sending with ØMQ/ZMQ
我有一个 protobuf 对象,我从 C# 应用程序(使用 clrZmq)发送到本地机器上的 C++ 服务(使用 zmq C++ 绑定)(用于测试)。我尝试使用以下
从 C# 发送我的对象
Taurus.Odds odds = Util.GetFakeOdds();
using (var context = ZmqContext.Create())
using (var socket = context.CreateSocket(SocketType.REQ))
{
byte[] buffer = null;
socket.Connect(TARGET); // TARGET = "tcp://127.0.0.1:6500"
Taurus.FeedMux mux = new Taurus.FeedMux();
mux.type = Taurus.FeedMux.Type.ODDS;
mux.odds = odds;
SendStatus status = socket.Send(mux.ToByteArray());
if (status == SendStatus.Sent)
{
int i;
byte[] arr = socket.Receive(buffer, SocketFlags.None, out i);
Taurus.Bet bet = buffer.ToObject<Taurus.Bet>();
}
...
}
我通过扩展方法
将我的 Taurus.Odds
对象序列化为 byte[]
public static byte[] ToByteArray(this object o)
{
if(o == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, o);
return ms.ToArray();
}
}
我在我的 C++ 应用程序中看到代码收到消息,但 C++ ZMQ 类 无法正确反序列化它。我有一些 Java 代码以相同的方式毫无问题地发送到 C++ 代码。我的问题是,我是否在上面通过 ZMQ 正确地发送了我的对象,如果没有,我做错了什么?
感谢您的宝贵时间。
这是你的错误:
I am serializing to my Taurus.Odds
object to byte[]
via the extension method
...
BinaryFormatter bf = new BinaryFormatter();
...
您似乎没有意识到BinaryFormatter
is. It is in no way related to ProtoBuf. The docs说了以下内容:
Serializes and deserializes an object, or an entire graph of connected objects, in binary format.
此二进制格式 是特定于 .NET 的实现细节。而且它 非常 死板,版本控制支持很差。它主要用于 .NET 远程处理时代,现在通常认为使用它是个坏主意,因为周围有 更好 的序列化程序。
如您所见,您的 C++ 应用无法读取它,因为它不是 protobuf 格式。
所以放弃这个方法并用一些适当的 protobuf 序列化代码替换它,如 in the protobuf-net docs 所解释的。您需要在对象中添加 [ProtoContract]
和 [ProtoMember]
属性。然后你可以这样写:
public static byte[] ToByteArray<T>(this T o)
{
if (o == null)
return null;
using (MemoryStream ms = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(ms, o);
return ms.ToArray();
}
}
我有一个 protobuf 对象,我从 C# 应用程序(使用 clrZmq)发送到本地机器上的 C++ 服务(使用 zmq C++ 绑定)(用于测试)。我尝试使用以下
从 C# 发送我的对象Taurus.Odds odds = Util.GetFakeOdds();
using (var context = ZmqContext.Create())
using (var socket = context.CreateSocket(SocketType.REQ))
{
byte[] buffer = null;
socket.Connect(TARGET); // TARGET = "tcp://127.0.0.1:6500"
Taurus.FeedMux mux = new Taurus.FeedMux();
mux.type = Taurus.FeedMux.Type.ODDS;
mux.odds = odds;
SendStatus status = socket.Send(mux.ToByteArray());
if (status == SendStatus.Sent)
{
int i;
byte[] arr = socket.Receive(buffer, SocketFlags.None, out i);
Taurus.Bet bet = buffer.ToObject<Taurus.Bet>();
}
...
}
我通过扩展方法
将我的Taurus.Odds
对象序列化为 byte[]
public static byte[] ToByteArray(this object o)
{
if(o == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, o);
return ms.ToArray();
}
}
我在我的 C++ 应用程序中看到代码收到消息,但 C++ ZMQ 类 无法正确反序列化它。我有一些 Java 代码以相同的方式毫无问题地发送到 C++ 代码。我的问题是,我是否在上面通过 ZMQ 正确地发送了我的对象,如果没有,我做错了什么?
感谢您的宝贵时间。
这是你的错误:
I am serializing to my
Taurus.Odds
object tobyte[]
via the extension method... BinaryFormatter bf = new BinaryFormatter(); ...
您似乎没有意识到BinaryFormatter
is. It is in no way related to ProtoBuf. The docs说了以下内容:
Serializes and deserializes an object, or an entire graph of connected objects, in binary format.
此二进制格式 是特定于 .NET 的实现细节。而且它 非常 死板,版本控制支持很差。它主要用于 .NET 远程处理时代,现在通常认为使用它是个坏主意,因为周围有 更好 的序列化程序。
如您所见,您的 C++ 应用无法读取它,因为它不是 protobuf 格式。
所以放弃这个方法并用一些适当的 protobuf 序列化代码替换它,如 in the protobuf-net docs 所解释的。您需要在对象中添加 [ProtoContract]
和 [ProtoMember]
属性。然后你可以这样写:
public static byte[] ToByteArray<T>(this T o)
{
if (o == null)
return null;
using (MemoryStream ms = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(ms, o);
return ms.ToArray();
}
}