套接字上的 Protobuf-net 序列化。未找到无参数构造函数 ProtoException

Waq*_*hah 5 .net c# protocol-buffers protobuf-net

我创建了一个应用程序,其中使用套接字完成进程间通信。当客户端连接到我创建的服务器并发送序列化消息时,该过程开始。这条消息,我使用 Protobuf-net 序列化,使用 SerializeWithLengthPrefix 并使用 DeserializeWithLengthPrefix 反序列化它。客户端将消息发送到服务器,后者将其完美地反序列化,但在服务器到客户端的情况下,情况并非如此。

主类是BaseMessage,它是抽象的。

[Serializable, ProtoContract, ProtoInclude(5001, typeof(LogonMessage))]
abstract public class BaseMessage
{
    public BaseMessage()
    {

    }

    abstract public int MessageType { get; }
}
Run Code Online (Sandbox Code Playgroud)

而 LogonMessage 实现了 BaseMessage 类。

[Serializable, ProtoContract]
public class LogonMessage : BaseMessage
{
    public LogonMessage()
    {

    }

    [ProtoMember(1)]
    public string Broker { get; set; }

    [ProtoMember(2)]
    public int ClientType { get; set; }

    public override int MessageType
    {
        get { return 1; }
    }
}
Run Code Online (Sandbox Code Playgroud)

初始握手后,客户端请求一些在 protobuf-net 帮助下序列化的服务,我端的本地服务器通过从 Web 上的另一台服务器请求数据来提供服务。这个消息从客户端传输到服务器是完美的。

当我的服务器从 Web 服务器接收数据时,它会对其进行序列化并将数据发送到客户端。但是这一次,当我尝试使用相同的过程在客户端反序列化数据时,出现以下异常:“找不到 BaseMessage 的无参数构造函数”

我使用以下代码行反序列化(这是发生异常的地方)。

BaseMessage baseMessage = Serializer.DeserializeWithLengthPrefix<BaseMessage>(networkStream, PrefixStyle.Base128);
Run Code Online (Sandbox Code Playgroud)

这就是消息在服务器上序列化的方式。

Serializer.SerializeWithLengthPrefix(networkStream, baseMessage, PrefixStyle.Base128);
Run Code Online (Sandbox Code Playgroud)

在客户端和服务器之间的连接开始时使用的 NetworkStream 存储在一个对象中,该对象存储在一个字典中。我从字典中的那个对象中挑选出相同的 NetworkStream 并使用它来将序列化数据发送到客户端(从服务器)。但是出现了上面提到的问题。有什么帮助吗?

提前致谢...

Mar*_*ell 4

这在任何 v2 版本中都应该可以正常工作;2.0.0.480 是当前在 NuGet 上公布的下载版本,但 2.0.0.580 也可用。我检查了 1.0.0.280 和 2.0.0.480,它们都没有显示此症状,所以我猜测您使用的是不同的版本。因此,我的建议是:确保您选择这两者之一(或更高版本,如果有的话)。

作为信息,您不需要[Serializable]protobuf-net,但它也没有什么坏处。另外,您的BaseMessage构造函数可能应该是protectedpublic对于类型的构造函数来说实际上没有意义abstract)。但由于编译器会自动为您完成所有这些工作,因此您可以简化:

[ProtoContract, ProtoInclude(5001, typeof(LogonMessage))]
abstract public class BaseMessage
{
    abstract public int MessageType { get; }
}


[ProtoContract]
public class LogonMessage : BaseMessage
{
    [ProtoMember(1)]
    public string Broker { get; set; }

    [ProtoMember(2)]
    public int ClientType { get; set; }

    public override int MessageType
    {
        get { return 1; }
    }
}
Run Code Online (Sandbox Code Playgroud)

其他想法:5001有点偏高;您将从低值包含编号中获得更高的效率。1跃入脑海。它们不必是普遍唯一的:只需在该类型中唯一即可。