ProtoBuf.ProtoException: вложенное сообщение не читается правильно (protobuf-net версия 2.4.0) - PullRequest
0 голосов
/ 22 декабря 2018

У меня есть два приложения (SocketClient и SocketServer), оба написаны на .NET core 2.1.SocketClient (работает на Unix-машине) читает файл размером ~ 10 ГБ и отправляет прочитанные байты через 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}");
    }
}

Этот код прекрасно работает с почти 96 миллионами успешно десериализованных SomeObject(файл содержит ~ 101 миллион объектов), и после этого он постоянно разрывается с сообщением ProtoBuf.ProtoException: вложенное сообщение не читается правильно.

Файл содержит байтовые массивы, полученные путем многократного вызова следующего метода (с пакетами SomeObject),Вывод одного одиночного вызова составляет ~ 270 КБ, который добавляется в файл.

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

Любая помощь высоко ценится!Спасибо за чтение.

Логика создания файла довольно проста.SomeObject содержит только три поля (строковый идентификатор, строковое логическое значение и двойное значение), и следующий метод вызывается несколькими потоками

    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);
            }
        }
    }
...