2009-08-11 156 views
1

对于网络应用程序,我们传输动态数据的方式是通过将结构体写入(void *)。这带来了一些问题,比如对std :: string做了这些事情。字符串可以是动态的长度,那么对方如何知道字符串结束的时间?我的想法是使用与Java的DataOutputStream类似的东西,我可以将任何变量传递给它,然后将它放入(void *)中。如果这不能完成,那么它很酷。我只是不喜欢对一个struct进行memcpying。有关它的东西似乎不太正确。C++字节流

感谢,
罗比

+1

这个问题不是很清楚(或者我的大脑不工作)。是否将std :: string复制到IN或OUT中?作为解释长度的空终止符有什么问题?为什么不先传输长度? memcpy一个结构有什么问题?为什么不使用正确的数据包结构和标识符来告诉你数据包的类型,以便双方知道他们正在发送和接收数据包? – Goz 2009-08-11 12:48:15

+0

std :: string被复制进去。解析两端收到的数据包不支持查找空终止符。首先传输长度,但传输一个int和三个可变长度的字符串。长度是所有人的总数。无论出于何种原因,对结构体进行memcpying看起来都不正确。我可能是错的,但那就是它的感觉。而且我们有一个合适的数据包结构,它的可变长度正在让我受益。 – Robbie 2009-08-11 12:53:14

回答

2

无可厚非的memcpy上的结构 - 为与结构充满了固定大小的缓冲区LNG。把一个动态变量放在那里,你必须以不同的方式对它进行序列化。

如果你在那里有一个std :: strings的结构体,那么创建一个流操作符并用它来格式化一个缓冲区。然后您可以将该缓冲区memcpy到数据传输。如果您有提升,请使用Boost::serialize,它为您完成所有这些工作(该链接还包含指向备用序列化库的链接)

注意:传递可变大小缓冲区的通常方法是先发送长度,然后许多字节的数据。有时您会看到数据传输,直到收到分隔符(并且该数据中的字段由另一个字符(例如逗号)分隔)。

+0

memcpy() - 网络上的一个结构有问题......不同的编译器会以不同的方式填充结构,所以数据很可能在接收端被误解。即使是相同的编译器也可以根据编译器的版本和/或优化设置来填充不同的东西。 传输数据的唯一安全方法是手动将该结构的每个成员变量封送到字节缓冲区,以便您可以精确控制字节布局。 – 2009-08-11 22:29:34

0

我看到这个问题的两个部分: - 数据的序列通过网络 - 如何将结构传递到网络堆栈

在网络上连载的数据,你需要一个协议。不一定非常困难;对于ASCII,即使是数据包结尾可能会有的cr/lf。如果您使用框架(如MFC),它可能会为您提供序列化功能;在这种情况下,你需要担心如何发送数据包。这往往可以很好地用于我分组化是:

<length><data_type>[data....][checksum] 

在这种情况下,校验和是可选的,并且如果该信号在DATA_TYPE进行(即确认为acklnowedgement)

零数据是可能的,例如

如果你正在使用结构化的memcpy,你需要考虑memcpy只能做一个浅拷贝。一旦通过网络传输指针就毫无价值;您应该从该指针传输数据(即您的字符串示例的内容)

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是一个基于数据包的协议,并且不会检查所有数据包是否按顺序到达,或者根本不在另一端。

所以总结。

  1. 对于动态数据,发送多个数据包,但有一个特殊的标志 说,更多的数据将到达完成此消息。
  2. 保持简单,如果您使用C++不假设数据包或数据 将包含空终止符,并且如果您决定使用空终止符,则检查与 有效负载相比的大小。