使用 Protobuf-net 发送二进制数据
Sending binary data with Protobuf-net
使用Protobuf-net发送二进制数组有什么特殊要求吗?我有一条消息 class,其中包含一些二进制数据:
[ProtoContract]
public class BitmapPackage : BaseMessage
{
[ProtoMember(1)]
public byte[] BitmapData;
}
尝试反序列化消息时,我捕获到 Protobuf-net 抛出的异常:
16:52:59.902: (007): [Error] Inner Exception in StartReceiveLoop():Message: Attempted to read past the end of the stream.Stack Trace: at ProtoBuf.ProtoReader.Ensure(Int32 count, Boolean strict) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 257
at ProtoBuf.ProtoReader.AppendBytes(Byte[] value, ProtoReader reader) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 921
at proto_4(Object , ProtoReader )
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line 57
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 775
at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 700
at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 588
at ProtoBuf.Serializer.Deserialize[T](Stream source) in c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 77
只有当我发送一个特定的位图时才会发生这种情况。所以我的问题是,在使用 protobuf-net 反序列化之前,我是否应该以某种方式 "escape" 二进制数据?
更新:
这是进行接收的代码:
private async Task StartReceiveLoop()
{
await Task.Yield();
while(!_readOpCancelToken.IsCancellationRequested)
{
try
{
var buffer = new byte[4096];
int bytesRx = await _pipe.ReadAsync(
buffer, 0, buffer.Length, _readOpCancelToken);
Logger.LogInfo("Pipe connection: Got " + bytesRx + " bytes");
if (bytesRx == 0) break;
if (_readOpCancelToken.IsCancellationRequested) break;
await _receivedDataStream.WriteAsync(buffer, 0, bytesRx);
if (_pipe.IsMessageComplete)
{
// Get out the routing data
_receivedDataStream.Position = 0;
byte[] intbuffer = new byte[4];
_receivedDataStream.Read(intbuffer, 0, 4);
int size = BitConverter.ToInt32(intbuffer, 0);
_receivedDataStream.Read(intbuffer, 0, 4);
int typeId = BitConverter.ToInt32(intbuffer, 0);
_receivedDataStream.Read(intbuffer, 0, 4);
int routeTag = BitConverter.ToInt32(intbuffer, 0);
messageObj = messageObj = Serializer.NonGeneric.Deserialize(messageType, _receivedDataStream);
// Process message on UI thread via tick queue
TickSystem.OneTimeTickQueue.Enqueue(new Action(() =>
{
ProcessMessageExtApp.ProcessThisMessage(messageObj);
}));
// Reset the stream
_receivedDataStream = new MemoryStream();
}
}
catch (Exception e)
{
Logger.LogError(
"Exception in StartReceiveLoop():" +
"Message: " + e.Message +
"Stack Trace: " + e.StackTrace);
if (e.InnerException != null)
{
Logger.LogError(
"Inner Exception in StartReceiveLoop():" +
"Message: " + e.InnerException.Message +
"Stack Trace: " + e.InnerException.StackTrace);
}
}
}
}
实际问题不是 Protobuf-net,而是 IsMessageComplete 过早发出信号这一事实。解决方法是使用字节数组写入管道服务器上的管道,而不是流复制并在完成每个数据包后刷新管道。
使用Protobuf-net发送二进制数组有什么特殊要求吗?我有一条消息 class,其中包含一些二进制数据:
[ProtoContract]
public class BitmapPackage : BaseMessage
{
[ProtoMember(1)]
public byte[] BitmapData;
}
尝试反序列化消息时,我捕获到 Protobuf-net 抛出的异常:
16:52:59.902: (007): [Error] Inner Exception in StartReceiveLoop():Message: Attempted to read past the end of the stream.Stack Trace: at ProtoBuf.ProtoReader.Ensure(Int32 count, Boolean strict) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 257 at ProtoBuf.ProtoReader.AppendBytes(Byte[] value, ProtoReader reader) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 921 at proto_4(Object , ProtoReader ) at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line 57 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 775 at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 700 at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 588 at ProtoBuf.Serializer.Deserialize[T](Stream source) in c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 77
只有当我发送一个特定的位图时才会发生这种情况。所以我的问题是,在使用 protobuf-net 反序列化之前,我是否应该以某种方式 "escape" 二进制数据?
更新: 这是进行接收的代码:
private async Task StartReceiveLoop()
{
await Task.Yield();
while(!_readOpCancelToken.IsCancellationRequested)
{
try
{
var buffer = new byte[4096];
int bytesRx = await _pipe.ReadAsync(
buffer, 0, buffer.Length, _readOpCancelToken);
Logger.LogInfo("Pipe connection: Got " + bytesRx + " bytes");
if (bytesRx == 0) break;
if (_readOpCancelToken.IsCancellationRequested) break;
await _receivedDataStream.WriteAsync(buffer, 0, bytesRx);
if (_pipe.IsMessageComplete)
{
// Get out the routing data
_receivedDataStream.Position = 0;
byte[] intbuffer = new byte[4];
_receivedDataStream.Read(intbuffer, 0, 4);
int size = BitConverter.ToInt32(intbuffer, 0);
_receivedDataStream.Read(intbuffer, 0, 4);
int typeId = BitConverter.ToInt32(intbuffer, 0);
_receivedDataStream.Read(intbuffer, 0, 4);
int routeTag = BitConverter.ToInt32(intbuffer, 0);
messageObj = messageObj = Serializer.NonGeneric.Deserialize(messageType, _receivedDataStream);
// Process message on UI thread via tick queue
TickSystem.OneTimeTickQueue.Enqueue(new Action(() =>
{
ProcessMessageExtApp.ProcessThisMessage(messageObj);
}));
// Reset the stream
_receivedDataStream = new MemoryStream();
}
}
catch (Exception e)
{
Logger.LogError(
"Exception in StartReceiveLoop():" +
"Message: " + e.Message +
"Stack Trace: " + e.StackTrace);
if (e.InnerException != null)
{
Logger.LogError(
"Inner Exception in StartReceiveLoop():" +
"Message: " + e.InnerException.Message +
"Stack Trace: " + e.InnerException.StackTrace);
}
}
}
}
实际问题不是 Protobuf-net,而是 IsMessageComplete 过早发出信号这一事实。解决方法是使用字节数组写入管道服务器上的管道,而不是流复制并在完成每个数据包后刷新管道。