对于联网应用程序,我们传输动态数据的方式是通过将结构备份到(void *)中。这会带来一些问题,例如当对std :: string进行此操作时。字符串可以是动态长度,那么对方如何知道字符串何时结束?我的想法是使用类似于Java的DataOuputStream的东西,我可以将任何变量传递给它,然后可以将它放入(void *)。如果这不能做到,那就很酷。我只是不喜欢memcpying结构。关于它的一些东西似乎不太正确。
谢谢,
罗比
答案 0 :(得分:2)
结构上的memcpy没有任何问题 - 因为结构中填充了固定大小的缓冲区。在那里放置一个动态变量,你必须以不同的方式序列化它。
如果你有一个带有std :: strings的结构,请创建一个流运算符并使用它来格式化缓冲区。然后,您可以将该缓冲区memcpy到数据传输。如果您有提升,请使用Boost::serialize为您完成所有这些操作(该链接还包含指向备用序列化库的链接)
注意:传递可变大小缓冲区的常用方法是先发送长度,然后再发送那么多字节的数据。有时您会看到传输的数据,直到收到分隔符(并且该数据中的字段由另一个字符(例如逗号)分隔。)
答案 1 :(得分:0)
我看到这个问题的两个部分: - 通过网络序列化数据 - 如何将结构传递到网络堆栈
要通过网络序列化数据,您需要一个协议。不一定很难;对于ASCII甚至是数据包端可能做的cr / lf。如果您使用框架(如MFC),它可能会为您提供序列化功能;在这种情况下,你需要担心如何在数据包中发送它。通常适合我的打包方式是:
<length><data_type>[data....][checksum]
在这种情况下,校验和是可选的,也可以是零数据,例如,如果信号是在data_type中携带的(即Ack for acklnowedgement)
如果你正在处理带结构的memcpy,你需要考虑memcpy只做一个浅拷贝。一旦通过网络传输,指针就毫无价值; instand你应该从该指针传输数据(即你的字符串示例的内容)
答案 2 :(得分:0)
要通过网络发送动态数据,您可以选择以下选项。
同一个数据包中的第一个选项。
void SendData()
{
int size;
char payload[256];
Send(messageType)
Send(size);
Send(payload)
}
第二个选项:
void SendData()
{
char payload[256];
Send(messageType)
Send(payload)
}
虽然在任何一种情况下,你都会面临更多的设计选择。在第一个示例中,您将发送消息类型,有效负载大小以及有效负载。
您拥有的第二个选项是您可以发送消息类型,然后您可以发送具有空终止符分隔符的字符串。
虽然任何一个选项都没有完全涵盖我认为你面临的问题。首先,您需要确定您是否正在构建游戏,您将使用哪种类型的协议,UDP? TCP?您将面临的第二个问题是最大数据包大小。然后,最重要的是你需要有框架,这样你就可以计算出不会被分段并丢失到网络间的最佳数据包大小。之后,您可以在客户端和服务器之间传输和接收的数据量方面进行带宽控制。
例如,大多数游戏接近这种情况的方式是使用以下内容识别每个数据包。
MessageType
MessageSize
CRCCheckSum
MessageID
void buffer[payload]
在需要发送动态数据的情况下,您将发送一系列数据包,而不仅仅是一个数据包。例如,如果您要通过网络发送文件,最好的选择是使用TCP / IP,因为它是一个流式协议,它可以使整个流安全地到达另一端。另一方面,UDP是基于数据包的协议,并且不会检查所有数据包是按顺序到达还是根本没有到达。
总之。