0

对于客户端/服务器应用程序,我需要发送和接收 c++ 对象。我不需要相应的类来做任何花哨的事情,但想要获得最大的性能(关于网络流量和计算)。所以我想简单地将它们作为二进制字符串传输。基本上我希望能够做到以下几点

//Create original object
MyClass oldObj();

//save to char array
char* save = new char[sizeof(MyClass)];
memcpy(save, &oldObj, sizeof(MyClass));

//Somewhere of course there would be the transfer to the client/server

//Read back from char array
MyClass newObj();
memcpy(&newObj, save, sizeof(MyClass));

我的问题:我的班级需要完成什么才能使它起作用?Naturaly Pointers 作为成员在转移到另一个应用程序时将不起作用。但是,我的 Class 被认为是 POD(在 c++03 和/或 c++11 中)并且没有任何指针或等价物(如 STL 容器)作为成员就足够了吗?

4

4 回答 4

3

两台机器都需要:

  1. 具有相同的字节序(对于 int)
  2. 相同的浮点表示(双精度)
  3. 所有类型的尺寸相同。
  4. 同一个编译器
  5. 用于构建应用程序的相同标志。
  6. 指针不能很好地转移。

但是网络将是这里最慢的部分。
与传输成本相比,序列化大多数对象的成本将无关紧要。当然,您的对象越大,成本就越高,但需要一段时间才能产生重大影响。

更高的维护成本也是您应该考虑的因素。

于 2013-01-11T23:31:55.067 回答
1

我的班级需要完成什么才能使其发挥作用?

  • 它不能有指针成员,你已经提到了。
  • 它不能有大小由实现定义的成员,例如int.
  • 由于字节顺序不同,它不能有整数成员。
  • 由于表示不同,它不能有浮点成员。
  • ......可能还有更多!

基本上,除了非常特别受限的情况外,您不能这样做。您必须选择一个协议并使您的数据符合它,才能安全地通过网络发送。

没什么大不了的,因为性能将受网络速度和延迟的限制,而不是受您的值符合协议所需的操作的限制。

于 2013-01-11T23:32:04.100 回答
1

您对运行它的硬件/操作系统有多少控制权?您是在编写超级便携的代码,还是仅在 32 位和 64 位 x86 Windows [例如] 上运行?

如上所述,要完全“超级便携”,您不能拥有任何形式的“实现定义”大小的对象(例如可以是 16、18、32、36 或 64 位的 int)。此类项目需要存储为已定义数字和顺序的字节,以确保在传输时不会被切断/重新排序。浮点数可能更糟......

许多“超级便携”应用程序将其数据存储为文本。它有点慢,但它使它易于移植,因为文本只是一个字节流,无论您在何种架构上运行它,并且无论您使用哪种机器,它的排序方式都相同(只要您坚持 0-9,A- Za-z, !?<>,.()*& 和其他一些字符——注意 EBCDIC 编码的机器,但它们倾向于处理“ascii-to-ebcdic”转换)。另一端只需要将文本转换回字符串/整数/浮点数/双精度,无论您需要什么。从整数到数字字符串的转换需要对每个数字进行一次除法(使用十六进制或 base-36 会更好一些,但会降低人类可读性 - 有时是好事,有时是坏事)。这显然比存储 4 个字节要慢。另一个缺点是它' s(取决于所使用的值)在文本中存储数字通常比二进制存储时间更长。所以你的网络数据包会大一点。这将比转换产生更大的影响,因为处理器可以在使用 10Gbit 网卡发送 1KB 所需的时间内进行大量数学运算。当然,您需要一些额外的字节(空格、逗号、换行符或其他任何可能的字符),以便您可以区分一个数字 123456 和三个 12、34、56。[当然,不需要使用“ ,“在每个之间]。一旦它到达,你需要一些代码来解析另一端的整个事情。因为处理器可以在使用 10Gbit 网卡发送 1KB 的时间内进行大量数学运算。当然,您需要一些额外的字节(空格、逗号、换行符或其他任何可能的字符),以便您可以区分一个数字 123456 和三个 12、34、56。[当然,不需要使用“ ,“在每个之间]。一旦它到达,你需要一些代码来解析另一端的整个事情。因为处理器可以在使用 10Gbit 网卡发送 1KB 的时间内进行大量数学运算。当然,您需要一些额外的字节(空格、逗号、换行符或其他任何可能的字符),以便您可以区分一个数字 123456 和三个 12、34、56。[当然,不需要使用“ ,“在每个之间]。一旦它到达,你需要一些代码来解析另一端的整个事情。

如果您知道您的系统总是有 32 位整数和 IEEE-754 浮点数 [这些非常常见!],那么您可能只需担心字节顺序即可。如果你知道它总是在“x86”或类似的地方,你也不必担心字节顺序。但是,当您决定“在 iphone 上运行我的代码将是一个好主意”时,您现在可能不得不修改您的代码。当然,您可以将其留给 iphone 方面以符合其余要求。

于 2013-01-12T00:09:18.220 回答
-4

class其他答案已经提到如何为此目的使用 a 。就个人而言,我更喜欢使用 astruct代替。在 C++ 中,astruct可以像 a 一样拥有成员方法/运算符、构造函数/析构函数、支持继承等class。但是,astruct具有定义明确且可预测的内存布局,并且可以通过#pragma语句显式对齐该布局以添加/删除编译器的隐式填充(我之前从未尝试过对齐 a class,但我认为它是受支持的)。struct对于必须在应用程序进程之外交换的数据,我总是使用 8 位对齐。出于所有意图和目的,在现代编译器中, astruct基本上与 a 相同class,只是其成员的默认可见性是public而不是private. 但我喜欢为了不同的目的而保留structclass分开。Astruct只是一个原始数据容器,您可以在内存中自由操作、覆盖等。Aclass是一个对象,其内存布局和填充是编译器定义的,不应被弄乱。

于 2013-01-11T23:47:41.637 回答