UDP 数据包序列化和开销消除

发布于 2024-11-30 18:33:50 字数 238 浏览 0 评论 0原文

我要序列化一个包含信息的数据包,它充当传入 udp 数据包的答案。传入的 UDP 数据包非常紧凑,并且包含我想要查看的信息。

当我发送回复时,数据包几乎大了 200 倍(1036 字节对 57 字节..),并且包含大量空格、类实例的名称及其结构(如可空等)。

这个问题听起来可能很宽泛,但这里的问题是什么?我知道我的解决方案是序列化整个对象,包括它的类名、命名空间等。收件人不需要、不会也不能接受此信息。他们需要直接进入数据结构。

I'm about serialize a paket with information, which act as an answer on a incoming udp paket. The incoming UDP paket is very compact and contains exactly the information I want to see.

When I send my reply, the packet is nearly 200 times bigger (1036 byte against 57 byte..) and contains a lot of white spaces, name of the class instance and it's structure (like nullable and so on).

The question may sounds wide but what are the problem here? I understand that my solution is serialize the whole object, including it's class name, namespace and so on. The recipient don't need, won't and Can't take this info. They need to go directly into the data structure.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忘羡 2024-12-07 18:33:50

您或许应该尝试 Protobuf。它支持属性序列化模型(事实上,它支持多种属性模型,包括 DataContract WCF 模型),并且比内置的 .Net 二进制序列化速度快得多(甚至比 DataContract 还要快) 序列化)。 Protobuf 也被设计得尽可能紧凑——所以你应该更少遇到数据包大小的问题。

编辑:您还可以通过使用接口来实现您自己的序列化范例。例如:

public interface IBinarySerializable
{
    void Serialize(BinaryWriter writer);
    void Deserialize(BinaryReader reader);
}

public static class BinaryReaderWriterExtensions
{
    public static void Write(this BinaryWriter writer, IBinarySerializable value)
    {
        value.Serialize(writer);
    }

    public static T Read<T>(this BinaryReader reader)
        where T : IBinarySerializable, new()
    {
        var val = new T();
        val.Deserialize(reader);
        return val;
    }

    public static void ReadInto(this BinaryReader reader, IBinarySerializable value)
    {
        value.Deserialize(reader);
    }

    public static void WriteList<T>(this BinaryWriter writer, IList<T> list, Action<BinaryWriter, T> singleValueWriter)
    {
        writer.Write(list.Count);
        foreach (var item in list)
            singleValueWriter(writer, item);
    }

    public static IEnumerable<T> ReadList<T>(this BinaryReader reader, Func<BinaryReader, T> singleValueReader)
    {
        var ct = reader.ReadInt32();
        for (var i = 0; i < ct; i++)
            yield return singleValueReader(reader);
    }
}

public class WantsToBeSerialized : IBinarySerializable
{
    public int ID;
    public string CustomerName;
    public List<string> Nicknames;
    public SomeOtherSerializableObject Thing;

    void IBinarySerializable.Serialize(BinaryWriter writer)
    {
        writer.Write(ID);
        writer.Write(CustomerName);
        writer.WriteList(Nicknames, (w, value) => w.Write(value));
        writer.Write(Thing);
    }

    void IBinarySerializable.Deserialize(BinaryReader reader)
    {
        ID = reader.ReadInt32();
        CustomerName = reader.ReadString();
        Nicknames = new List<string>(reader.ReadList(x => x.ReadString()));
        Thing = reader.Read<SomeOtherSerializableObject>();
    }
}

You should probably try out Protobuf. It supports the attributed serialization model (in fact, it supports several attributed models, including the DataContract WCF model), and is significantly faster than built-in .Net binary serialization (faster than even DataContract serialization). Protobuf is also designed to be as compact as possible - so you should have fewer problems with packet size.

Edit: You could also implement your own serialization paradigm, by using an interface. For example:

public interface IBinarySerializable
{
    void Serialize(BinaryWriter writer);
    void Deserialize(BinaryReader reader);
}

public static class BinaryReaderWriterExtensions
{
    public static void Write(this BinaryWriter writer, IBinarySerializable value)
    {
        value.Serialize(writer);
    }

    public static T Read<T>(this BinaryReader reader)
        where T : IBinarySerializable, new()
    {
        var val = new T();
        val.Deserialize(reader);
        return val;
    }

    public static void ReadInto(this BinaryReader reader, IBinarySerializable value)
    {
        value.Deserialize(reader);
    }

    public static void WriteList<T>(this BinaryWriter writer, IList<T> list, Action<BinaryWriter, T> singleValueWriter)
    {
        writer.Write(list.Count);
        foreach (var item in list)
            singleValueWriter(writer, item);
    }

    public static IEnumerable<T> ReadList<T>(this BinaryReader reader, Func<BinaryReader, T> singleValueReader)
    {
        var ct = reader.ReadInt32();
        for (var i = 0; i < ct; i++)
            yield return singleValueReader(reader);
    }
}

public class WantsToBeSerialized : IBinarySerializable
{
    public int ID;
    public string CustomerName;
    public List<string> Nicknames;
    public SomeOtherSerializableObject Thing;

    void IBinarySerializable.Serialize(BinaryWriter writer)
    {
        writer.Write(ID);
        writer.Write(CustomerName);
        writer.WriteList(Nicknames, (w, value) => w.Write(value));
        writer.Write(Thing);
    }

    void IBinarySerializable.Deserialize(BinaryReader reader)
    {
        ID = reader.ReadInt32();
        CustomerName = reader.ReadString();
        Nicknames = new List<string>(reader.ReadList(x => x.ReadString()));
        Thing = reader.Read<SomeOtherSerializableObject>();
    }
}
两相知 2024-12-07 18:33:50

这里的问题是,您的对方需要一个扁平的、类似 xml 的结构,它可能看起来像 XML,但根据 xml 规范,它是无效的/格式良好的。

您可以调整 .net 序列化程序(DataContract 或 XMLSerializer),只要您记住输出的内容可能不再有效或格式良好。检查以下两个链接,它们应该为您指明正确的方向。

编辑:使用 XMLSerializer 添加了 BinaryFormatting,不确定您的输出格式,但也许这是一个帮助。

class Program
{
    static void Main(string[] args)
    {
        TestObject data = new TestObject() { Name = "Claus", Firstname = "Santa"};

        MemoryStream stream = new MemoryStream();

        XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
        xsn.Add(String.Empty, String.Empty);

        XmlSerializer serializer = new XmlSerializer(typeof(TestObject));

        XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream);

        serializer.Serialize(binaryDictionaryWriter, data,xsn);

        binaryDictionaryWriter.Flush();

        stream.Seek(0, SeekOrigin.Begin);

        StreamReader reader = new StreamReader(stream);

        string s = reader.ReadToEnd();
    }
}

[Serializable()]
public class TestObject
{
    [XmlAttribute]
    public string Name { get; set; }

    [XmlIgnore]
    public string Firstname { get; set; }

}

The problem here is, that your counterpart is expecting a flat, xml-like structure, which may look like XML, but is not valid/wellformed according the xml specifications.

You can tweak the .net serializers (DataContract or XMLSerializer), as long as you have in mind that what you´re outputting might no longer be a valid or wellformed. Check the following two links, they should point you in the right direction.

EDIT: Added BinaryFormatting using XMLSerializer, not sure about your output format but maybe this is a help.

class Program
{
    static void Main(string[] args)
    {
        TestObject data = new TestObject() { Name = "Claus", Firstname = "Santa"};

        MemoryStream stream = new MemoryStream();

        XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
        xsn.Add(String.Empty, String.Empty);

        XmlSerializer serializer = new XmlSerializer(typeof(TestObject));

        XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream);

        serializer.Serialize(binaryDictionaryWriter, data,xsn);

        binaryDictionaryWriter.Flush();

        stream.Seek(0, SeekOrigin.Begin);

        StreamReader reader = new StreamReader(stream);

        string s = reader.ReadToEnd();
    }
}

[Serializable()]
public class TestObject
{
    [XmlAttribute]
    public string Name { get; set; }

    [XmlIgnore]
    public string Firstname { get; set; }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文