C# - 通过网络序列化数据包

发布于 2024-12-22 03:14:31 字数 546 浏览 0 评论 0原文

我正在开发一个发送大量数据包的网络应用程序。目前,我的序列化方法只是一种 hack,它获取对象列表并将它们转换为由管道字符“|”分隔的字符串。并将其刷新到网络流中(或者只是通过 UDP 发送出去)。

我正在 C# 中寻找一个更干净的解决方案,同时最大限度地减少 数据包大小(因此没有巨大的 XML 序列化)。

我的 BinaryFormatter 体验很慢。我还考虑通过将数据包编码为 base64 字符串来压缩我的数据包,然后在客户端对其进行解码。我想要一些意见来了解这将如何影响我的应用程序的性能。

另外,还有一个简单的问题:

我的设置创建了 2 个套接字(一个 TCP 和 UDP),并且客户端单独连接到这两个套接字。数据根据需要被刷新(TCP 用于重要内容,UDP 用于不重要内容)。这是我第一次同时使用 TCP/UDP,我想知道

是否有更统一的方法,虽然看起来并非如此。

一如既往地感谢您的大力支持。

I am developing a networked application that sends a lot of packets. Currently, my method of serialization is just a hack where it takes a list of objects and converts them into a string delimited by a pipe character '|' and flushes it down the network stream (or just sends it out through UDP).

I am looking for a cleaner solution to this in C# while minimizing
packet size (so no huge XML serialization).

My experiences with BinaryFormatter is SLOW. I am also considering compressing my packets by encoding them into base64 strings and them decoding them on the client side. I would like some input on seeing how this will effect the performance of my application.

Also, another quick question:

My setup creates 2 sockets (one TCP and UDP) and the client connects individually to these two sockets. Data is flushed down either one based off of the need (TCP for important stuff, UDP for unimportant stuff). This is my first time using TCP/UDP simultaneously and was wondering

if there is a more unified method, although it does not seem so.

Thanks as always for the awesome support.

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

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

发布评论

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

评论(4

心凉 2024-12-29 03:14:31

我会使用类似于 Google 的 Protocol Buffers 的二进制协议。通过 John Skeet 的 protobuf-csharp-port,可以使用 WriteDelimitedTo 和 MergeDelimitedFrom 方法分别在 IMessage 和 IBuilder 上。这些将在消息中添加字节数前缀,以便可以在另一端使用它们。定义消息非常简单:

message MyMessage {
    required int32 number = 1;
}

然后使用 ProtoGen.exe< 构建 C# 类/a> 然后就进城了。 protobuffers(特别是 protobuf-csharp-port)的一大好处是,并非每个端点都需要同时升级。以前的版本可以添加和使用新字段,而不会出现错误。这种版本独立性可能非常强大,但如果您没有计划的话,也可能会咬伤您;)

I would use a binary protocol similar to Google's Protocol Buffers. Using John Skeet's protobuf-csharp-port one can use the WriteDelimitedTo and MergeDelimitedFrom methods on IMessage and IBuilder respectively. These will prefix the message with the number of bytes so that they can consumed on the other end. Defining messages are really easy:

message MyMessage {
    required int32 number = 1;
}

Then you build the C# classes with ProtoGen.exe and just go to town. One of the big benefits to protobuffers (specifically protobuf-csharp-port) is that not every endpoint needs to be upgraded at the same time. New fields can be added and consumed by previous versions without error. This version independence can be very powerful, but can also bite you if you're not planning for it ;)

我纯我任性 2024-12-29 03:14:31

您可以考虑使用 ProtoBuf 进行序列化

You could look into using ProtoBuf for the serilization

彼岸花似海 2024-12-29 03:14:31

我个人使用过以下系统:
有抽象的Packet类,所有的数据包都派生自。 Packet 类定义了两个虚拟方法:

void SerializeToStream(BinaryWriter serializationStream)
void BuildFromStream(BinaryReader serializationStream)

这种手动序列化使得创建小尺寸的数据包成为可能。
在发送到套接字之前,数据包带有长度前缀,并带有唯一的数据包类型 ID 号。然后,接收端可以使用 Activator.CreateInstance 构建适当的数据包并调用 BuildFromStream 来重建数据包。

数据包示例:

class LocationUpdatePacket : Packet
{
   public int X;
   public int Y;
   public int Z;

   public override void SerializeToStream(BinaryWriter serializationStream)
   {
         serializationStream.Write(X);
         serializationStream.Write(Y);
         serializationStream.Write(Z);
   }
   public override void BuildFromStream(BinaryReader serializationStream)
   {
         X = serializationStream.ReadInt32();
         Y = serializationStream.ReadInt32();
         Z = serializationStream.ReadInt32();
   }
}

I personally have used following system:
Have abstract Packet class, all packets are derived from. Packet class defines two virtual methods:

void SerializeToStream(BinaryWriter serializationStream)
void BuildFromStream(BinaryReader serializationStream)

This manual serialization makes it possible to create small sized packets.
Before sending to socket, packets are length prefixed and prefixed with unique packet type id number. Receiving end can then use Activator.CreateInstance to build appropriate packet and call BuildFromStream to reconstruct the packet.

Example packet:

class LocationUpdatePacket : Packet
{
   public int X;
   public int Y;
   public int Z;

   public override void SerializeToStream(BinaryWriter serializationStream)
   {
         serializationStream.Write(X);
         serializationStream.Write(Y);
         serializationStream.Write(Z);
   }
   public override void BuildFromStream(BinaryReader serializationStream)
   {
         X = serializationStream.ReadInt32();
         Y = serializationStream.ReadInt32();
         Z = serializationStream.ReadInt32();
   }
}
故事与诗 2024-12-29 03:14:31

我正在开发一个发送大量数据包的网络应用程序

查看 networkComms.net,一个开源项目网络通信库,可能会节省您相当多的时间。它结合了 protobuf 进行序列化,这里是一个示例,第 408 行。

I am developing a networked application that sends a lot of packets

Check out networkComms.net, an open source network communication library, might save you a fair bit of time. It incorporates protobuf for serialisation, an example of which is here, line 408.

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