使用 UdpClient C# 发送对象

Posted

技术标签:

【中文标题】使用 UdpClient C# 发送对象【英文标题】:Sending objects with UdpClient C# 【发布时间】:2011-09-13 08:48:11 【问题描述】:

我目前正在 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);
        
    

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

【问题讨论】:

您的 ToBytes() 方法将无法正常工作,因为序列化的表单大于 1024 字节。为什么不使用ToArray() method? 【参考方案1】:

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

还要注意 UDP 不可靠。无法保证您的消息一定会到达。

【讨论】:

请注意,这只是 BinaryFormatter 要求。大多数其他序列化程序不需要这个。 是的,我想我必须创建一个类库。这就说得通了。此外,我使用 UDP 只是为了了解我有哪些替代方案。谢谢!【参考方案2】:

BinaryFormatter 与类型元数据密切相关。这不是一个好的选择,因为你有不同的类型。实际上,IMO 无论如何都不是一个好选择 :) 它对版本的容忍度不是很高,而且不可移植。

我会在这里公开推荐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) 写入数据。

如果需要,您也可以在没有属性的情况下工作,这需要一点更多设置,但不会太多。

【讨论】:

【参考方案3】:

您可能会遇到依赖不满足的问题。这可能是由不同的命名空间或尝试序列化未安装在服务器上的外部组件引起的。

说:你发送MyApp1.MyFoo类型的对象。MyFoo 类也在您的服务器中定义,但定义为 MyApp2.MyFoo(这很愚蠢,意味着您必须修复您的设计)。服务器不知道如何创建MyApp1.MyFoo 的对象,因为它不够聪明,无法发现他也定义了这个类,但命名为MyApp2.MyFoo

您应该使用相同的命名空间。这就是他们的目的。此外,它们使处理依赖关系更容易。 MyApp.ServerMyApp.Client 交谈看起来不错 ;)。

我希望你明白这一点。

【讨论】:

以上是关于使用 UdpClient C# 发送对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# UdpClient 发送大数据?

C#:UdpClient 很快调用 close() 时不发送数据

C# UdpClient使用

C# UdpClient 设置超时时间

UDP 协议 C# UdpClient乱序接收数据包丢失的问题 Socket ReceiveBufferSize

C#里使用UdpClient和线程来创建UDP网络通讯