我目前正在处理在一个应用程序(C ++)中序列化的代码,需要在另一个应用程序(C#)中反序列化它。我正在尝试使用google proto + protobuf-net,但有些事情失败了。
.cc和.cs消息定义文件都是使用它们各自的编译器从同一个.proto文件生成的。
数据通过UDP发送,消息(~40B)很容易放入单个数据报中。
在C ++大小上,boost :: asio用于传输数据,相关代码为:
ProtocolBufferdata data;
...
boost::asio::streambuf b;
std::ostream os(&b);
data.SerializeToOstream(&os);
m_Socket.send_to(b.data(), m_Endpoint);
我很确定这是正常的,因为使用wireshark我至少可以看到我在数据报中所期望的所有字符串。在C#方面,使用Begin / End接收,我们在回调中有以下内容:
byte[] buffer ....
public void ReceiveData(IAsyncResult iar)
{
try
{
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceive(iar);
using (MemoryStream memStream = new MemoryStream())
{
memStream.Write(buffer, 0, recv);
ProtoData data = ProtoBuf.Serializer.Deserialize<ProtoData >(memStream);
onReceive(data);
}
}
catch (Exception ex)
{
...
}
finally
{
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), socket);
}
}
缓冲区确实具有预期的字节数,并具有告诉字符串。 protobuf-net容器具有所有默认值。
我对这里发生的事情感到有些困惑,并且几乎不可能将调试器附加到客户端应用程序,因为它被部署为另一个与远程调试器不兼容的应用程序的插件。我很感激任何建议,这让我很难过。
答案 0 :(得分:9)
快退您的信息流 - 它就在最后,因此Read
将不会返回任何数据:
memStream.Write(buffer, 0, recv);
memStream.Position = 0; // <===========here
ProtoData data = ProtoBuf.Serializer.Deserialize<ProtoData>(memStream);
或者,使用重载的构造函数来准备流:
using (MemoryStream memStream = new MemoryStream(buffer, 0, recv))
{
ProtoData data = ProtoBuf.Serializer.Deserialize<ProtoData>(memStream);