我处于困境,无法决定以下情况。请专家帮忙。
场景:在两个框中运行的两个进程之间存在TCP / IP通信。
通信方法1:套接字上基于流的通信。在接收器端,他将接收整个字节缓冲区并将前几个固定字节解释为头并对其进行去序列化并了解消息长度并开始获取该长度的消息并对其进行反序列化并继续执行下一个消息头上....
通信方法2:将所有消息放入向量中,向量将驻留在类对象中。一次序列化类对象并发送给接收器。 Receiver反序列化类对象并逐个读取向量数组。
请告诉我哪种方法有效,如果有其他方法,请指导我。
基于类的数据传输和基于结构的数据传输的优缺点也适用于哪种场景?
答案 0 :(得分:5)
你的问题缺乏一些关键细节,并且混合了不同的问题,使任何提供良好答案的尝试都感到沮丧。
具体来说,方法2神秘地“序列化”和“反序列化”对象并包含向量,而不指定如何完成的任何细节。在实践中,细节是方法1中提到的类型。因此,1和2不是替代方案,除非您在使用序列化库和从头开始执行(在这种情况下我会说使用库)因为你是新手,图书馆更有可能做到正确。)
我可以说:
read()
或recv()
从套接字中读取尽可能多的数据
所以,让我强调一下:不要假设你从套接字的任何给定读取中收到任何超过1个字节:如果你说一个20字节的标题你应该循环读取,直到你遇到错误或已经汇编全部20个字节。在单个write()
或send()
中发送20个字节并不意味着20个字节将呈现给单个read()
/ recv()
。 TCP是一种字节流协议,您必须在提供它们时采用任意数量的字节,等待有足够的数据来解释它。同样,准备好获取比客户端可以在单个write()
/`send()中编写的更多数据。
基于类的数据传输和基于结构的数据传输的优缺点也适用于哪种场景?
这些条款完全是假的。 C ++中的类和结构几乎完全相同 - 用于对数据和相关函数进行分组的机制(它们的区别仅在于它们 - 默认情况下 - 将基类和数据成员公开给客户端代码)。要么具有成员函数,要么不具有帮助序列化和反序列化数据的支持代码。例如,最简单且最典型的支持是operator<<
和/或operator>>
流功能。
如果你想将这类流媒体功能与ad-hoc“写二进制块,读取二进制块”方法(可能从结构视为POD而不支持代码)进行对比,那么我会说更喜欢流媒体功能尽可能,从流式传输到人类可读的表示,因为它们将使您的系统更容易,更快速地开发,调试和支持。一旦你对此非常满意,如果运行时性能需要它,那么使用二进制表示进行优化。如果你很好地编写了序列化代码,你就不会发现较粗糙的void*/#bytes
数据模型和正确的每个成员序列化之间的性能差别很大,但后者可以更容易地支持异常情况 - 跨不同系统的可移植性大小的整数/长整数等,不同的字节顺序,有意的选择重新浅层与深层复制指向数据等....
我还建议查看boost序列化库。即使你不使用它,它也应该让你更好地理解在C ++中如何合理地实现这种东西。
答案 1 :(得分:0)
两种方法都是等价的。在两者中,您必须发送带有消息大小和标识符的标头才能反序列化。如果您假设第一个选项由序列化的“类”组成,就像普通消息一样,则必须实现相同的“代码”。
您必须考虑的另一件事是消息的大小,以便使用完整的TCP缓冲区来优化通信。如果您的第一个方法消息很少,请尝试使用更大的消息来提高通信率,例如您描述的第二个选项。
答案 2 :(得分:0)
请记住,不安全只是直接通过将结构或类解释为一个字节序列直接流出结构或类,即使它是一个简单的POD - 有像endianness这样的问题(不太可能对于我们大多数人来说,这是一个现实世界的问题),以及结构对齐/填充( 是一个潜在的问题)。
C ++没有任何内置的序列化/反序列化,您可能需要自己动手或查看boost Serialization或Google的protobuf等内容。
答案 3 :(得分:0)
如果它不是家庭作业或学习项目,那么在TCP流水平上摆弄IPC可能没什么意义,特别是如果这不是人们熟悉的话。
使用消息库(如ØMQ)发送和接收完整的消息,而不是字节流。