C++ 字节流

发布于 2024-08-02 00:07:47 字数 272 浏览 7 评论 0原文

对于网络应用程序,我们传输动态数据的方式是通过将结构体memcpying到(void*)中。 这会带来一些问题,例如对 std::string 执行此操作时。 字符串可以是动态长度的,那么对方如何知道字符串何时结束呢? 我的一个想法是使用类似于 Java 的 DataOuputStream 的东西,我可以将任何变量传递给它,然后将其放入 (void*) 中。 如果这不能做到,那就很酷了。 我只是不太喜欢 memcpying 结构。 事情似乎有些不太对劲。

谢谢,
罗比

For a networked application, the way we have been transmitting dynamic data is through memcpying a struct into a (void*). This poses some problems, like when this is done to an std::string. Strings can be dynamic length, so how will the other side know when the string ends? An idea I had was to use something similiar to Java's DataOuputStream, where I could just pass whatever variables to it and it could then be put into a (void*). If this can't be done, then its cool. I just don't really like memcpying a struct. Something about it doesn't seem quite right.

Thanks,
Robbie

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

美人迟暮 2024-08-09 00:07:47

结构上的 memcpy 没有任何问题 - 就像 lng 一样,结构中充满了固定大小的缓冲区。 将动态变量放在那里,您必须以不同的方式序列化它。

如果您有一个包含 std::strings 的结构,请创建一个流运算符并使用它来格式化缓冲区。 然后,您可以将该缓冲区 memcpy 到数据传输中。 如果您有 boost,请使用 Boost::serialize 为您完成所有这一切(该链接还包含指向替代序列化库的链接)

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

nothing wrong with memcpy on a struct - as lng as the struct is filled with fixed-size buffers. Put a dynamic variable in there and you have to serialise it differently.

If you have a struct with std::strings in there, create a stream operator and use it to format a buffer. You can then memcpy that buffer to the data transport. If you have boost, use Boost::serialize which does all this for you (that link also has links to alternative serialization libs)

Notes: the usual way to pass a variable-size buffer is to begin by sending the length, then that many bytes of data. Occasionally you see data transferred until a delimiter is received (and fields within that data are delimited themselves by another character, eg a comma).

后eg是否自 2024-08-09 00:07:47

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

要通过网络序列化数据,您需要一个协议。 不一定很困难; 对于 ASCII,甚至作为数据包结尾的 cr/lf 也可以。 如果您使用框架(如MFC),它可能会为您提供序列化功能; 在这种情况下,您需要担心如何将其打包发送。 通常对我来说效果很好的打包是:

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

在这种情况下,校验和是可选的,并且零数据也是可能的,例如,如果信号在 data_type 中携带(即确认确认),

如果您正在处理 memcpy对于结构,您需要考虑 memcpy 仅进行浅复制。 指针一旦通过网络传输就毫无价值; 例如,您应该从该指针传输数据(即字符串示例的内容)

I see two parts of this question:
- serialization of data over a network
- how to pass structures into a network stack

To serialize data over a network, you'll need a protocol. Doesn't have to be difficult; for ASCII even a cr/lf as packet end may do. If you use a framework (like MFC), it may provide serialization functions for you; in that case you need to worry about how to send this in packets. A packetization which often works well for me is :

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

In this case the checksum is optional, and also zero-data is possible, for instance if the signal is carried in the data_type (i.e. Ack for acklnowedgement)

If you're working on the memcpy with structures, you'll need to consider that memcpy only makes a shallow copy. A pointer is worthless once transmitted over a network; instand you should transmit the data from that pointer (i.e. the contents of your string example)

南渊 2024-08-09 00:07:47

要通过网络发送动态数据,您有以下选项。

同一数据包中的第一个选项。

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++ 时不假设数据包或数据
    将包含一个空终止符并检查与
    如果您决定使用空终止符,则有效负载。

For sending dynamic data across the network you have the following options.

First option in the same packet.

void SendData()
{
   int size;
   char payload[256];

   Send(messageType)
   Send(size);
   Send(payload)
}

Second option:

void SendData()
{
   char payload[256];

   Send(messageType)
   Send(payload)
}

Though in either situation, you will be faced with more of a design choice. In the first example you would send the message type, and the payload size and also then the payload.

The second option you have is you can send the message type and then you can send the string that has a delimiter of null terminator.

Though either option does not cover fully the problem your facing I think. Firstly, you need to determine if you're building a game what type of protocal you will be using, UDP? TCP? The second problem you will be facing is the maximum packet size. Then on top of that you need to have the framework in place so that you can calculate the optimum packet size that will not be fragmented and lost to the inter web. After that you have bandwidth control in regards to how much data you can transmitted and receive between the client and server.

For example the way that most games approach this situation is each packet is identified with the following.

MessageType
MessageSize
CRCCheckSum
MessageID
void buffer[payload]

In situation where you need to send dynamic data you would send a series of packets not just one. For example if you were to send a file accross the network the best option would to use TCP/IP because its a streaming protocal and it garnentees that the complete stream arrives safly to the other end. On the other hand UDP is a packet based protocal and is does not do any checking that all packets arrived in order or at all on the other end.

So in conclusion.

  1. For dynamic data, send multiple packets but with a special flag
    to say more data is to arrive to complete this message.
  2. Keep it simple and if your working with C++ dont assume the packet or data
    will contain a null terminator and check the size compared to the
    payload if you decide to use a null terminator.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文