C# Protobuf-net:如何从网络流中连续反序列化?
C# Protobuf-net: how do I deserialize consecutively from a network stream?
我正在(感激地)使用 Marc Gravell 优秀的 Protobuf-net Protocol Buffers 库。不幸的是,我不够聪明,无法理解反序列化通过网络传入的对象的正确方法。
作为我努力的基础,我遵循以下问题中的建议:
Issue deserializing (protocolBuffer) serialized data using protobuf-net
protobuf: consecutive serialize and deserialize to/from socket
我在整个会话期间(几分钟……几小时……谁知道呢?)保持一个 TCP 连接打开,并使用与连接持续时间一样长的单一网络流。我通过此流收到许多 PB 消息。
考虑到我正在使用 "TryDeserializeWithLengthPrefix",我曾期望库能够解决等待流的问题,以获得足够的数据来解析整个对象。但事实并非如此。
我写了一个简单的测试:
[Test]
public void DeserializeSimpleObjectInParts ()
{
SimpleObject origin = new SimpleObject();
byte[] wholeObj = ProtobufSerializer.SerializeToByteArray ( origin );
int length = wholeObj.Length;
int midpoint = length / 2;
int sizeA = midpoint;
int sizeB = length - midpoint;
byte[] aaa = new byte[sizeA];
byte[] bbb = new byte[sizeB];
for ( int i = 0; i < midpoint; i++ )
{
aaa [ i ] = wholeObj [ i ];
}
for ( int j = midpoint; j < length; j++ )
{
bbb [ j - midpoint ] = wholeObj [ j ];
}
using ( MemoryStream streamA = new MemoryStream ( aaa ) )
{
using ( MemoryStream streamB = new MemoryStream ( bbb ) )
{
streamA.Position = 0;
streamB.Position = 0;
Debug.LogDebug ( "streamA.Length = " + streamA.Length + ", streamB.Length = " + streamB.Length );
object resultA = null;
bool succeededA = false;
try {
succeededA = ProtobufSerializer.Deserialize ( streamA, out resultA );
}
catch ( Exception e )
{
Debug.LogDebug ( "Exception = " + e );
Debug.LogDebug ( "streamA.Position = " + streamA.Position + ", streamA.Length = " + streamA.Length );
}
}
}
}
请注意,在上面,"ProtobufSerializer.Deserialize" 只是通过我自己的服务 class 直接调用 "TryDeserializeWithLengthPrefix"。类型编码业务就在那里。
当我运行这个测试时,抛出以下异常:
System.IO.EndOfStreamException: Failed to read past end of stream.
This advice from our friends at Google 建议我有责任查看套接字代码中的长度前缀。但这有什么帮助呢? C# 网络流没有可供我比较的长度 属性。
我真的必须执行中间步骤 运行 在流上循环,构建正确大小的字节数组,然后从中创建新的流并将其传递到 Protobuf-net 中吗?这似乎是一种反模式和性能打击。
我在这里错过了什么?
Given that I am using "TryDeserializeWithLengthPrefix", I had expected the library to sort out waiting on the stream to have enough data to parse a whole object.
没有可靠和有效的方法来 "sort out waiting" 抽象 Stream 对象。
C# network streams don't have a Length property for me to compare against.
统计你从套接字流写入缓冲流的数据。那将是你的 "Length" 属性 来与你开始时得到的长度前缀进行比较。一旦你有足够的数据,寻找缓冲区流回到前缀并将它传递给反序列化器以获取你的对象。现在再次寻找缓冲区流并重新使用它来获取下一条消息。重复。
我正在(感激地)使用 Marc Gravell 优秀的 Protobuf-net Protocol Buffers 库。不幸的是,我不够聪明,无法理解反序列化通过网络传入的对象的正确方法。
作为我努力的基础,我遵循以下问题中的建议:
Issue deserializing (protocolBuffer) serialized data using protobuf-net
protobuf: consecutive serialize and deserialize to/from socket
我在整个会话期间(几分钟……几小时……谁知道呢?)保持一个 TCP 连接打开,并使用与连接持续时间一样长的单一网络流。我通过此流收到许多 PB 消息。
考虑到我正在使用 "TryDeserializeWithLengthPrefix",我曾期望库能够解决等待流的问题,以获得足够的数据来解析整个对象。但事实并非如此。
我写了一个简单的测试:
[Test]
public void DeserializeSimpleObjectInParts ()
{
SimpleObject origin = new SimpleObject();
byte[] wholeObj = ProtobufSerializer.SerializeToByteArray ( origin );
int length = wholeObj.Length;
int midpoint = length / 2;
int sizeA = midpoint;
int sizeB = length - midpoint;
byte[] aaa = new byte[sizeA];
byte[] bbb = new byte[sizeB];
for ( int i = 0; i < midpoint; i++ )
{
aaa [ i ] = wholeObj [ i ];
}
for ( int j = midpoint; j < length; j++ )
{
bbb [ j - midpoint ] = wholeObj [ j ];
}
using ( MemoryStream streamA = new MemoryStream ( aaa ) )
{
using ( MemoryStream streamB = new MemoryStream ( bbb ) )
{
streamA.Position = 0;
streamB.Position = 0;
Debug.LogDebug ( "streamA.Length = " + streamA.Length + ", streamB.Length = " + streamB.Length );
object resultA = null;
bool succeededA = false;
try {
succeededA = ProtobufSerializer.Deserialize ( streamA, out resultA );
}
catch ( Exception e )
{
Debug.LogDebug ( "Exception = " + e );
Debug.LogDebug ( "streamA.Position = " + streamA.Position + ", streamA.Length = " + streamA.Length );
}
}
}
}
请注意,在上面,"ProtobufSerializer.Deserialize" 只是通过我自己的服务 class 直接调用 "TryDeserializeWithLengthPrefix"。类型编码业务就在那里。
当我运行这个测试时,抛出以下异常:
System.IO.EndOfStreamException: Failed to read past end of stream.
This advice from our friends at Google 建议我有责任查看套接字代码中的长度前缀。但这有什么帮助呢? C# 网络流没有可供我比较的长度 属性。
我真的必须执行中间步骤 运行 在流上循环,构建正确大小的字节数组,然后从中创建新的流并将其传递到 Protobuf-net 中吗?这似乎是一种反模式和性能打击。
我在这里错过了什么?
Given that I am using "TryDeserializeWithLengthPrefix", I had expected the library to sort out waiting on the stream to have enough data to parse a whole object.
没有可靠和有效的方法来 "sort out waiting" 抽象 Stream 对象。
C# network streams don't have a Length property for me to compare against.
统计你从套接字流写入缓冲流的数据。那将是你的 "Length" 属性 来与你开始时得到的长度前缀进行比较。一旦你有足够的数据,寻找缓冲区流回到前缀并将它传递给反序列化器以获取你的对象。现在再次寻找缓冲区流并重新使用它来获取下一条消息。重复。