c++ - 如何增量编码 C/C++ 结构以通过套接字传输

标签 c++ c serialization encoding struct

我需要以相当高的更新速率通过线路发送 C 结构(使用 UDP 套接字,有时可能使用 XDR),这可能会导致几 khz 的大量冗余和不必要的流量。

这是因为,结构中的某些数据有时可能没有更改,所以我认为针对先前的 C 结构对当前 C 结构进行增量编码似乎是个好主意,非常像“diff” ".

但我想知道,执行此类操作的最佳方法是什么,最好是以可移植的方式同时确保维护数据完整性?是否可以简单地对数据进行异或并像这样继续?

同样,该方法保持足够的可扩展性也很重要,以便可以将新字段添加到结构中或在必要时重新排序(填充),这听起来好像也需要版本控制信息。

任何想法或指示(是否有现有的图书馆?)将不胜感激!

谢谢

编辑:感谢所有提供答案的人,非常感谢详细程度,我意识到我可能不应该提到 UDP,因为这实际上不是主要问题,因为已经有相应的在 UDP 之上实现的协议(protocol)解决了上述困难,因此这个问题实际上是针对对结构进行 delta 编码的可行方法,而不是将 UDP 特别用作传输机制。

最佳答案

UDP 不保证给定的数据包确实被接收到,因此将您传输的任何内容编码为“与上次的差异”是有问题的——您无法知道您的对方具有相同的数据包关于“上一次”的想法。本质上,您必须在 UDP 之上构建一些开销来检查收到了哪些数据包(用唯一 ID 标记每个数据包)——每个尝试走这条路线的人都会同意,您经常会发现自己更多或更多减少在 UDP 之上复制 TCP 流式传输基础设施……只是,很可能,没有那么可靠和发达(尽管不可否认,有时您可以利用有效负载的非常特殊的特性,以获得一些相对于普通好产品的适度优势旧的 TCP)。

您的传输是否需要是单向的,从发送方到接收方?如果是这种情况(即,接收方发送确认或重新传输是 Not Acceptable ),那么沿着这些路线您真的无能为力。想到的一件事:如果接收方暂时不同步是可以的,那么发送方可以发送两种数据包——一种是结构当前值的完整图片,另一种是标识独特的标签,至少每(比如)5 分钟发送一次(因此实际上,如果接收器错过了两个“大数据包”,它可能会不同步长达 15 分钟);一个只有来自最后一个“大数据包”的更新(差异),包括大数据包的识别唯一标签和(例如)您提到的 XOR 的游程编码版本。

当然,一旦准备好运行长度编码版本,服务器将比较它的大小与整个结构的大小,并且只有在节省大量的情况下才发送增量类型的数据包,否则它也可以比需要的时间早一点发送大数据包(提高可靠性)。 received 将跟踪它收到的最后一个大数据包唯一标记,并且仅应用与其相关的增量(有助于防止丢失数据包和乱序交付的数据包,具体取决于您想让客户变得多么复杂)。

版本控制和 c 的需要,具体取决于你的意思(对于结构的 C 布局应该如何看待的发送者和接收者有不同的想法是否需要定期沟通?他们如何握手了解双方都知道哪些版本?等) ,将增加更多的复杂性,但这实际上是另一个问题,标题中总结的核心问题已经足够大了;-)。

如果您能负担得起从接收方偶尔返回发送方的元消息(确认或请求重新发送),那么您可以根据游戏中的各种数字参数设计不同的策略。我怀疑 acks 必须非常频繁才能做很多好事,因此重新发送大数据包的请求(特别标识的数据包或“无论你有什么最新的”)可能是剔除选项空间的最佳元策略(否则有爆炸的危险;-)。如果是这样,那么发送方可能很幸运地不知道接收方正在使用什么策略来请求大数据包重发,您可以在接收方使用各种此类策略进行试验,而无需重新部署发送方。

如果没有一些具体细节,很难提供更多帮助,即至少所有数字参数的大概数字——数据包大小、发送频率、发送方与接收方不同步的容忍时间,一组网络参数等等。但我希望这种有点笼统的分析和建议仍然有所帮助。

关于c++ - 如何增量编码 C/C++ 结构以通过套接字传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1618591/

相关文章:

c++ - 用于枚举图中所有节点值的伪迭代器操作

c++ - 我似乎无法掌握 less than 和 more than 运营商背后的基础知识,有人可以确定我哪里出错了吗?

c - gcc 在更改变量声明顺序后保留内存分配

c - Linux C : Accessing shared memory fails with `Invalid Argument` even though it was just created

haskell - 如何对数据对象进行自动数据序列化?

c++ - 如何使用 Qt 在队列中创建多个线程?

c++ - C++ 或 ANSI C 所用的周期数?

c++ - 为什么 VC++ 2013 RC 不支持 C99 指定的初始值设定项?

serialization - 序列化元组类型 - 模块 core::tuple 是私有(private)的

c - protobuf-c 中的重复子消息