Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 套接字上的Protobuf网络序列化。未找到无参数构造函数ProtoException_C#_.net_Protocol Buffers_Protobuf Net - Fatal编程技术网

C# 套接字上的Protobuf网络序列化。未找到无参数构造函数ProtoException

C# 套接字上的Protobuf网络序列化。未找到无参数构造函数ProtoException,c#,.net,protocol-buffers,protobuf-net,C#,.net,Protocol Buffers,Protobuf Net,我创建了一个应用程序,其中进程间通信使用套接字完成。当客户端连接到我创建的服务器并发送序列化消息时,该过程开始。这个消息,我使用Protobuf net序列化,使用SerializeWithLengthPrefix,并使用DeserializeWithLengthPrefix反序列化。客户机向服务器发送消息,服务器将其完全反序列化,但在服务器到客户机的情况下,情况并非如此 主类是BaseMessage,它是抽象的 [Serializable, ProtoContract, ProtoInclud

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

主类是BaseMessage,它是抽象的

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

    }

    abstract public int MessageType { get; }
}
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; }
    }
}
在初始握手之后,客户机在protobuf net的帮助下请求一些序列化的服务,而我端的本地服务器通过从web上的另一台服务器请求数据来提供服务。从客户端到服务器的消息传输是完美的

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

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

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


提前感谢…

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

关于信息,protobuf-net不需要
[Serializable]
,但这也没有什么坏处。此外,您的
BaseMessage
构造函数可能应该受到
保护
public
对于
抽象类型的构造函数没有意义)。但由于编译器会自动为您完成所有这些工作,因此您可以简化:

[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; }
    }
}

其他想法:
5001
有点偏高;您将从低值包含数字中获得更好的效率<代码>1
跃入脑海。它们不一定都是唯一的:只是在该类型中是唯一的。

只是补充一点,我试图反序列化一个未查找到源的MemoryStream,并得到“没有为BaseObject找到无参数构造函数”异常,即使该类确实有无参数构造函数

var tdp = new DerivedObject("Test");
using (var ms  = new MemoryStream())
{
    Serializer.Serialize(ms,tdp);
    //was missing this line
    ms.Seek(0, SeekOrigin.Begin);

    var tdp2 = Serializer.Deserialize<DerivedObject>(ms);
}
var tdp=新的衍生对象(“测试”);
使用(var ms=new MemoryStream())
{
Serializer.Serialize(ms,tdp);
//他漏了这一行
Seek女士(0,SeekOrigin.Begin);
var tdp2=序列化程序。反序列化(ms);
}

我知道这是在这个问题得到回答后的几年,但对于其他人来说,我只是遇到了一个问题,我使用了一个抽象基类,得到了“没有为{className}找到无参数构造函数”的消息,但原因完全错误。。。我真傻,我是从一个记忆流中反序列化的,里面什么都没有(显然,当时我并不知道)。令人沮丧的哑巴。正确的错误消息应该是:
“id10t错误-无法反序列化任何内容,dum dum!”

因为错误消息指的是一些构造函数问题,以及抽象类的使用,这使我认为我没有正确地使用库(即-没有正确地使用repective Proto*属性修饰类/成员,等等)

要点是:对这条错误消息持保留态度——您的异常根源可能与我的类似;退一步,看看你访问protobuf net API的地方周围的活动部件,确保那里没有任何愚蠢的事情发生,然后再把头撞到墙上,从外面搜索一个库(也就是说,在本例中,实际上工作正常)

如何重现错误?有一堆嘈杂的代码会让你从实际的bug中分心,并伴随着一条转移注意力的错误信息。。。像这样:

[TestClass]
public class UnitTestJammieJawns
{
    [TestMethod]
    public void ProtobufAbstract_TestMethod()
    {
        var sub = new Sub() { AbstractInt = 234 , OtherInt32 = 987, SomeString = "qwer" };

        byte[] buffer = null;
        using (var ms = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(ms, sub);  // works - hooray!
            buffer = ms.ToArray();  // we've got binary content, people!
        }

        Sub obj = null;
        using (var ms = new MemoryStream())  // woops... you forgot the provide the serialized object - should be: new MemoryStream(buffer) 
        {
            obj = ProtoBuf.Serializer.Deserialize<Sub>(ms);  // <- throws exception (this is good) with misleading message (this is not so good)
        }
    }
}

[ProtoContract]
[ProtoInclude(1, typeof(Sub))]
public abstract class Super
{
    public abstract int AbstractInt { get; set; }

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

[ProtoContract]
public class Sub : Super
{
    [ProtoMember(2)]
    private int asdf;

    public override int AbstractInt
    {
        get
        {
            return asdf;
        }
        set
        {
            asdf = value;
        }
    }

    [ProtoMember(3)]
    public int OtherInt32 { get; set; }
}
[TestClass]
公共类UnitTestJammieJawns
{
[测试方法]
public void ProtobufAbstract_TestMethod()
{
var sub=new sub(){AbstractInt=234,OtherInt32=987,SomeString=“qwer”};
字节[]缓冲区=空;
使用(var ms=new MemoryStream())
{
ProtoBuf.Serializer.Serialize(ms,sub);//works-万岁!
buffer=ms.ToArray();//各位,我们有二进制内容!
}
Sub-obj=null;
使用(var ms=new MemoryStream())//woops…您忘记了提供序列化对象的方法-应该是:new MemoryStream(buffer)
{

obj=ProtoBuf.Serializer.Deserialize(ms);//此错误消息似乎是各种不同错误的总括,如和所指出的

另一个问题是,如果您反序列化的数据不是protobuf

var tdp = new DerivedObject("Test");
using (var ms  = new MemoryStream())
{
    JsonSerializer.Serialize(ms,tdp); //should be protobuf
    ms.Seek(0, SeekOrigin.Begin);

    var tdp2 = Serializer.Deserialize<DerivedObject>(ms);
}
var tdp=新的衍生对象(“测试”);
使用(var ms=new MemoryStream())
{
序列化(ms,tdp);//应该是protobuf
Seek女士(0,SeekOrigin.Begin);
var tdp2=序列化程序。反序列化(ms);
}
错误

“未找到无参数构造函数”


我知道,当协议缓冲区中的二进制流不是子类(通过[ProtoInclude]链接)时,就在begin stream(二进制数据中的第一个)上。

请问您使用的是什么版本的protobuf net?Thanx Marc…我确实使用了r580,但包中的文件夹中有许多DLL(仅CoreOnly、Full等)我想知道哪一个DLL
[TestClass]
public class UnitTestJammieJawns
{
    [TestMethod]
    public void ProtobufAbstract_TestMethod()
    {
        var sub = new Sub() { AbstractInt = 234 , OtherInt32 = 987, SomeString = "qwer" };

        byte[] buffer = null;
        using (var ms = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(ms, sub);  // works - hooray!
            buffer = ms.ToArray();  // we've got binary content, people!
        }

        Sub obj = null;
        using (var ms = new MemoryStream())  // woops... you forgot the provide the serialized object - should be: new MemoryStream(buffer) 
        {
            obj = ProtoBuf.Serializer.Deserialize<Sub>(ms);  // <- throws exception (this is good) with misleading message (this is not so good)
        }
    }
}

[ProtoContract]
[ProtoInclude(1, typeof(Sub))]
public abstract class Super
{
    public abstract int AbstractInt { get; set; }

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

[ProtoContract]
public class Sub : Super
{
    [ProtoMember(2)]
    private int asdf;

    public override int AbstractInt
    {
        get
        {
            return asdf;
        }
        set
        {
            asdf = value;
        }
    }

    [ProtoMember(3)]
    public int OtherInt32 { get; set; }
}
var tdp = new DerivedObject("Test");
using (var ms  = new MemoryStream())
{
    JsonSerializer.Serialize(ms,tdp); //should be protobuf
    ms.Seek(0, SeekOrigin.Begin);

    var tdp2 = Serializer.Deserialize<DerivedObject>(ms);
}