繁体   English   中英

从套接字读取到缓冲区

[英]Reading from a socket into a buffer

这个问题看似简单,但我认为并不是那么简单。 也许我想得太多,但我仍然想知道。

假设我们必须从TCP套接字读取数据,直到遇到某些特殊字符为止。 数据必须保存在某个地方。 我们不知道数据的大小,因此我们不知道要使缓冲区多大。 在这种情况下,可能有哪些选择?

  1. 使用realloc随着更多数据到达而扩展缓冲区。 这种方法提出了一些问题。 使用realloc对性能有何影响? 它可能会移动内存,因此如果缓冲区中有很多数据(并且可能有很多数据),我们将花费大量时间来移动字节。 我们应该扩展多少缓冲区大小? 我们每次都加倍吗? 如果是,那所有浪费的空间怎么办? 如果我们稍后以较小的大小调用realloc,它将截断未使用的字节吗?

  2. 以恒定大小的块分配新缓冲区,并将它们链接在一起。 这就像C ++标准库中的双端队列容器一样,可以快速添加新数据。 这也有一些问题,例如我们应该将块制作多大以及如何处理未使用的空间,但至少它具有良好的性能。

你对此的看法如何? 这两种方法哪一种更好? 也许我还没有考虑其他方法?

PS:

就我个人而言,我更倾向于第二种解决方案,因为我认为,如果我们“回收”这些块而不是每次需要一个块时都进行动态分配,那么它可以变得非常快。 我能看到的唯一问题是它会伤害局部性,但是我认为它对我的目的(处理类似HTTP的请求)并不十分重要。

谢谢

我更喜欢第二种。 您还可以考虑只使用一个原始缓冲区并处理收到的数据,然后再从套接字接收另一束数据,即在遇到特殊字符之前开始处理数据。

无论如何,我都不建议使用原始内存和重新分配,而是使用具有自己重新分配的std::vector ,或使用std::array作为固定大小的缓冲区。

您可能还对Boost.Asio的socket_iostream感兴趣,它在原始缓冲区上方提供了另一个抽象层。

方法2听起来更好,但是解析器上可能会有很大的变化……即,一旦找到特殊标记,则在解析HTTP请求时处理非连续的缓冲区可能比重新分配大的缓冲区更昂贵或更复杂(方法1)。 网络:如果解析器比较琐碎,请使用2,否则请使用1。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM