C # protobuf Ошибка десериализации с ZMQ, недопустимый тип записи - PullRequest
0 голосов
/ 18 декабря 2018

У меня две программы.с помощью сервера создайте DiscoverServerMessage, сериализуйте его с помощью protobuf и отправьте с помощью ZMQ.В клиентской части десериализовать сообщение, но ошибка:

Ivalid wire-type; this usually means you have over-written a file without truncating or setting the length.

У меня ниже класса в проекте dll.

[ProtoContract]
public class DiscoverServerMessage 
{
    [ProtoMember(1)]
    public int Port { get; set; }
    [ProtoMember(2)]
    public string IP { get; set; }
    [ProtoMember(3)]
    public string ServerName { get; set; }
    public DiscoverServerMessage() { }
}

В проекте сервера есть этот код:

public class Server
{
    static void Main(string[] args)
    {
        ZContext ctx = new ZContext();
        ZSocket broadcastSrocket = new ZSocket(ctx, ZSocketType.PUB);
        broadcastSrocket.Connect("tcp://127.0.0.1:2666");
        ZFrame zfr;
        DiscoverServerMessage message = new DiscoverServerMessage() { Port = 2667 , ServerName = "My" };
        message.IP = "127.0.0.1";
        using (MemoryStream str = new MemoryStream())
        {
            Serializer.SerializeWithLengthPrefix(str,message,PrefixStyle.Fixed32);
            zfr = new ZFrame(str.ToArray());
        }
        broadcastSrocket.Send(zfr);
    }
}

В клиентской программе:

public class Server
{
    static void Main(string[] args)
    {
        ZContext ctx = new ZContext();
        ZSocket subSocket = new ZSocket(ctx, ZSocketType.SUB);
        subSocket.Connect("tcp://127.0.0.1:2666");
        subSocket.SubscribeAll();
        ZError err;
        ZFrame zfr = subSocket.ReceiveFrame(out err);
        DiscoverServerMessage message;
        using (MemoryStream stream = new MemoryStream(zfr.Read()))
        {
            message = Serializer.DeserializeWithLengthPrefix<DiscoverServerMessage >(stream,PrefixStyle.Fixed32);
        }
    }
}

в чем моя ошибка?

1 Ответ

0 голосов
/ 18 декабря 2018

Первое, что нужно сделать, это забыть о части сериализации и просто проверить, было ли то, что вы отправили, тем, что вы получили, поэтому - получите копию того, что str.ToArray() (сервер), и сравнитеэто к тому, что zfr.Read() (клиент).Если две полезные нагрузки не идентичны: все остальные ставки отключены .Самый простой способ сделать это, как правило, через hex, поэтому:

(сервер):

byte[] blob = str.ToArray();
string hex = BitConverter.ToString(blob); // <== get a copy of this somehow
zfr = new ZFrame(blob);
...

(клиент)

byte[] blob = zfr.Read();
string hex = BitConverter.ToString(blob); // <== get a copy of this somehow
using (MemoryStream stream = new MemoryStream(blob))
...

и просто проверьте: являются ли онидве шестнадцатеричные последовательности идентичны?

Примечание: поскольку вы используете протокол кадрирования (ZFrame), вам здесь фактически не нужен префикс длины , но ... он не долженне больно.Это выглядит как будто вы используете соответствующий код на каждом конце здесь - и следующее (под влиянием вашего кода) отлично работает:

static class Program
{
    static void Main()
    {
        byte[] blob;

        // taken from server code
        using (MemoryStream str = new MemoryStream())
        {
            DiscoverServerMessage message = new DiscoverServerMessage() { Port = 2667, ServerName = "My" };
            message.IP = "127.0.0.1";

            Serializer.SerializeWithLengthPrefix(str, message, PrefixStyle.Fixed32);
            blob = str.ToArray();
        }
        System.Console.WriteLine(BitConverter.ToString(blob));

        // taken from client code
        using (MemoryStream stream = new MemoryStream(blob))
        {
            DiscoverServerMessage message;
            message = Serializer.DeserializeWithLengthPrefix<DiscoverServerMessage>(stream, PrefixStyle.Fixed32);
            Console.WriteLine(message.Port);
            Console.WriteLine(message.ServerName);
            Console.WriteLine(message.IP);
        }

    }
}

Вывод здесь:

12-00-00-00-08-EB-14-12-09-31-32-37-2E-30-2E-30-2E-31-1A-02-4D-79
2667
My
127.0.0.1

Если мы сделаем то же самое, просто используя Serialize / Deserialize (без префикса длины), мы получим (как и ожидалось):

08-EB-14-12-09-31-32-37-2E-30-2E-30-2E-31-1A-02-4D-79
2667
My
127.0.0.1

Так что должно работать с префиксом длины или без него, если клиент и сервер согласны (что они встречаются в вашем коде).

...