ProtoBuf.ProtoException:子消息读取不正确(protobuf net 2.4.0版本)



我有两个应用程序(SocketClient和SocketServer)都是用编写的。NET核心2.1。SocketClient(在unix机器上运行)读取大小约为10GB的文件,并通过Socket发送读取的字节。

var serverAddress = new IPEndPoint(IPAddress.Parse(args[0]), Convert.ToInt32(args[1]));
using (var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
clientSocket.Connect(serverAddress);
using (var f = new FileStream(args[2], FileMode.Open, FileAccess.Read))
{
using (var read = new BinaryReader(f, Encoding.UTF8))
{
const int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int count;
while ((count = read.Read(buffer, 0, buffer.Length)) != 0)
{
int byteSend = clientSocket.Send(buffer, 0, count, SocketFlags.None);
totalBytesSend += byteSend;
Console.WriteLine($"Sent bytes {byteSend}");
}
}
}
}

SocketServer(运行在windows机器上)接收发送的字节并尝试对其进行反序列化:

using (NetworkStream stream = client.GetStream())
{
if (!stream.CanRead) return;
while (true)
{
Serializer.DeserializeWithLengthPrefix<SomeObject[]>(stream, PrefixStyle.Fixed32);
Console.WriteLine($"{count += d.Length}");
}
}

这段代码可以很好地处理近9600万个SomeObject成功反序列化(文件包含约1.01亿个对象),之后它会一直中断消息ProtoBuf。ProtoException:子消息读取不正确。

该文件包含通过重复调用以下方法(使用批SomeObject)获得的字节数组。一个调用的输出大约为270KB,它被附加到文件中。

public static byte[] GetSerialisedWithLengthPrefix(SomeObject[] dto)
{
using (var ms = new MemoryStream())
{
Serializer.SerializeWithLengthPrefix(ms, dto, PrefixStyle.Fixed32);
return ms.ToArray();
}
}

非常感谢您的帮助!!感谢阅读。

文件创建逻辑非常直接。SomeObject只包含三个字段(字符串Id、字符串LogicalDateTime&double Value),下面的方法由多个线程调用

Dump(SomeObject[])
{
using (var ms = new MemoryStream())
{
requiredBytes = Serializer.SerializeWithLengthPrefix(ms, SomeObject.ToArray(), PrefixStyle.Fixed32);
}
lock (locker)
{
using (FileStream file = new FileStream(Filepath, FileMode.Append, FileAccess.Write, FileShare.Read))
using (BinaryWriter writer = new BinaryWriter(file, Encoding.UTF8))
{
writer.Write(requiredBytes);
}
}
}

我遇到过这个异常,在我的情况下,类的结构被更改,反序列化将无法工作。

[DataContract]
public class Foo {
[DataMember(Order = 1]
public int Bar;
}

如果我将Bar更改为CCD_ 1或CCD_。

最新更新