使用UdpClient发送对象的方法(C#)

5

我目前正在Visual Studio 2010中进行测试。我创建了一个客户端和服务器,它们都将通过UdpClient连接。

我想从客户端向服务器发送一个对象。 我有两种方法将对象转换为字节并将其转换为对象。 现在,当我测试我的应用程序时,一旦服务器接收到对象,我就无法将其转换回对象。

我的服务器看到对象已经被接收并尝试将其从字节转换为对象,但是这会导致错误。

System.Runtime.Serialization.SerializationException was unhandled   Message=Unable to find assembly

因为这两个应用程序位于不同的命名空间中,所以这似乎是可以的...

以下是我用于转换的方法;在客户端和服务器上都相同

public byte[] ToBytes() {
        using (MemoryStream stream = new MemoryStream()) {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);

            stream.Position = 0;

            byte[] byteRij = new byte[1024];

            stream.Read(byteRij, 0, (int)stream.Length);

            return byteRij;
        }
    }

    public static Datagram ToDatagram(byte[] rij) {
        using (MemoryStream stream = new MemoryStream()) {
            stream.Write(rij, 0, rij.Length);

            stream.Position = 0;

            BinaryFormatter formatter = new BinaryFormatter();
            return (Datagram)formatter.Deserialize(stream);
        }
    }

我该如何解决这个问题? 提前感谢。

1
如果序列化形式大于1024字节,您的ToBytes()方法将无法正常工作。为什么不使用ToArray()方法呢? - svick
3个回答

3

您需要将所有序列化的类放在一个类库项目中。在服务器和客户端中都使用该库。

此外,请注意UDP不可靠。不能保证您的消息是否到达。


请注意,这仅是BinaryFormatter的要求。对于大多数其他序列化程序,您不需要这样做。 - Marc Gravell
是的,我认为我需要制作一个类库。那很有道理。另外,我正在使用UDP只是为了学习我有哪些替代方案。谢谢! - kendepelchin

3

BinaryFormatter深度依赖于类型元数据。由于您有不同的类型,因此它不是一个好选择。实际上,在我看来,它根本不是一个好选择 :) 它不太兼容版本,并且不可移植。

在这里,我公开推荐protobuf-net(披露:我编写了它)。它是免费的OSS,但使用google的protobuf格式解决了所有BF问题。它很容易设置和使用,速度更快,输出比BinaryFormatter更小。由于它是基于合同的,因此您可以在每个端点具有不同的类型,只要它们在合同上达成一致(匹配字段编号等)。

例如:

[ProtoContract]
public class Foo {
    [ProtoMember(1)]
    public string X {get;set;}
    [ProtoMember(2)]
    public int Y {get;set;}
}

然后只需使用ProtoBuf.Serializer.Serialize(stream, object)将数据写入。

如果需要,您也可以在不使用属性的情况下进行操作,这需要一些设置,但并不多。


2
您可能遇到了无法满足的依赖关系问题。这可能是由于不同的命名空间或尝试序列化未安装在服务器上的外部组件所导致的。
例如,您发送了类型为MyApp1.MyFoo的对象。
MyFoo也在您的服务器上定义,但是是作为MyApp2.MyFoo(这很愚蠢,意味着您需要修复设计)。服务器不知道如何创建MyApp1.MyFoo对象,因为它不够聪明,无法找出它还定义了这个类,但是命名为MyApp2.MyFoo
您应该使用相同的命名空间。这就是它们的作用。此外,它们使处理依赖关系变得更容易。而且,MyApp.ServerMyApp.Client之间的通信看起来很好。
希望您能理解。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接