通过Boost TCP发送大块数据?

时间:2009-10-21 04:40:47

标签: c++ networking boost tcp network-programming

我必须通过TCP将网格数据从一台计算机发送到另一台计算机......这些网格可能相当大。我很难想到通过TCP发送它们的最佳方式是因为我对网络编程知之甚少。

这是我需要适合通过TCP发送的缓冲区的基本类结构:

class PrimitiveCollection
{
    std::vector<Primitive*> primitives;
};

class Primitive 
{
    PRIMTYPES primType; // PRIMTYPES is just an enum with values for fan, strip, etc...
    unsigned int numVertices;
    std::vector<Vertex*> vertices;
};


class Vertex
{
    float X;
    float Y;
    float Z;
    float XNormal;
    float ZNormal;
};

我正在使用Boost库及其TCP内容......它非常易于使用。您只需填充缓冲区并通过TCP发送即可 但是,当然这个缓冲区只能是这么大,我最多可以发送2兆字节的数据。

那么将上述类结构放入需要的缓冲区并通过网络发送的最佳方法是什么?我还需要在接收端反序列化。

非常感谢任何指导。

编辑:我在再次阅读之后意识到这确实是一个更普遍的问题,并不是特定于Boost ...它更多的是分块数据并发送它的问题。然而,我仍然有兴趣看看Boost是否有任何可以在某种程度上抽象出来的东西。

4 个答案:

答案 0 :(得分:3)

您是否尝试过使用Boost的TCP?我不明白为什么2MB会成为转移的问题。我假设我们正在谈论以100mbps或1gbps运行的局域网,一台拥有足够RAM的计算机,并且不必具有&gt; 20ms的响应时间?如果你的目标是从一台计算机到另一台计算机只需要2MB,那么只需发送它,TCP就会为你处理它。

我有一个TCP延迟检查工具,我用Boost编写,试图发送各种大小的缓冲区,我经常检查高达20MB,这些似乎没有问题。

我想我想说的是,除非你知道自己有问题,否则不要花时间开发解决方案: - )

---------解决方案实施--------

现在我已经掌握了几分钟,我经历了快速实施你所谈论的内容:https://github.com/teeks99/data-chunker有三大部分:

序列化器/解串器,boost有自己的,但它不比滚动你自己好多了,所以我做到了。

发件人 - 通过TCP连接到接收器并发送数据

Receiver - 等待发件人的连接并解压缩收到的数据。

我在zip中包含了.exe,运行Sender.exe / Receiver.exe - help以查看选项,或者只看主页。

更详细的解释: 打开两个命令提示符,然后转到两个命令提示符中的DataChunker \ Debug。 在其中一个中运行Receiver.exe 在另一台计算机上运行Sender.exe(可能在另一台计算机上运行,​​在这种情况下,在可执行文件名后添加--remote-host = IP.ADD.RE.SS,如果您想尝试多次发送和--num -sends = 10发送十次)。 查看代码,您可以看到正在发生的事情,在respecitve main()函数中创建TCP套接字的接收者和发送者端。发送者创建一个新的PrimitiveCollection并用一些示例数据填充它,然后序列化并发送它...接收器将数据反序列化为一个新的PrimitiveCollection,此时原始集合可以被其他人使用,但我刚刚写了到它完成的控制台。

编辑:将示例移至github。

答案 1 :(得分:2)

没有什么花哨的东西,我记得在我的网络课程中:

  • 向接收方发送消息,询问它可处理的数据块大小
  • 至少采用这些和你自己的发送功能,然后回复说:
    • 您将发送的尺寸,发送的数量
  • 在你得到之后,只需发送每个块。你会想要等待“好”回复,所以你知道你不会浪费时间发送给不在那里的客户。这也是客户发送“我正在取消”消息而不是“确定”消息的好时机。
  • 发送,直到所有数据包都以“确定”回复
  • 数据已转移。

这是有效的,因为TCP可以保证按顺序交付。 UDP需要包号(用于订购)。

除了您发送压缩数据外,压缩是相同的。 (数据是数据,一切都取决于你如何解释它)。只需确保告知数据的压缩方式:)

至于例子,我所能挖掘的只有this pageold question。我认为你所做的事情会与Boost.Serialization一起很好地发挥作用。

答案 2 :(得分:2)

我想再补充一点 - 设置TCP套接字缓冲区大小,以便在一定程度上提高套接字性能。

有一个实用程序Iperf可以测试TCP套接字的交换速度。我在Windows上运行了100 Mbs LAN中的一些测试。使用8Kb默认TCP窗口大小时,速度为89 Mbits / sec,TCP窗口大小为64Kb,速度为94 Mbits / sec。

答案 3 :(得分:-1)

除了如何分块和传递数据之外,您应该考虑的另一个问题是平台差异。如果两台计算机是相同的架构,并且两侧运行的代码是同一版本的相同编译器,那么您应该可以只在网络上转储原始内存结构并使其在另一台上运行侧。但是,如果一切都不一样,你可能会遇到有关字节序,结构填充,字段对齐等问题。

通常,最好为内存表示分别定义数据的网络格式。该格式可以是二进制格式,在这种情况下,数值应转换为标准格式(主要是将字节序更改为“网络顺序”,即大端),或者它可以是文本格式。许多网络协议选择文本,因为它消除了许多格式问题,并且因为它使调试更容易。就个人而言,我真的很喜欢JSON。它不是太冗长,每种编程语言都有很好的库,人类阅读和理解起来非常容易。

定义网络协议时要考虑的关键问题之一是接收方何时知道它已收到所有数据。有两种基本方法。首先,您可以在消息的开头发送一个明确的大小,然后接收者知道继续读取,直到获得那么多字节。另一种是使用某种消息结束分隔符。后者的优点是你不必事先知道你要发送多少字节,但缺点是必须弄清楚如何确保消息结束分隔符不能出现在消息。

一旦你决定数据在流经网络时应该如何构建,那么你应该找到一种方法将内部表示转换为该格式,理想情况是以“流”方式,这样你就可以遍历数据结构,将其中的每一部分转换为网络格式并将其写入网络套接字。

在接收方,您只需撤消该过程,将网络格式解码为适当的内存格式。

我对你的案例的建议是使用JSON。 2 MB不是很多数据,因此生成和解析的开销不会很大,您可以直接在JSON中轻松表示您的数据结构。生成的文本将是自我分隔的,人类可读的,易于流式传输,并且易于在目标端解析回内存。

相关问题