从套接字读入缓冲区

时间:2012-12-07 08:56:14

标签: c++ sockets memory buffer

这个问题可能看似简单,但我认为这不是那么简单。或者也许我在想这个,但我还是想知道。

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

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

  2. 以恒定大小的块分配新缓冲区并将它们链接在一起。这与C ++标准库中的deque容器非常相似,允许快速追加新数据。这也有一些问题,比如我们应该做多大的块以及如何处理未使用的空间,但至少它具有良好的性能。

  3. 您对此有何看法?这两种方法中的哪一种更好?也许还有其他一些方法我没有考虑过?

    P.S:

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

    由于

2 个答案:

答案 0 :(得分:0)

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

在任何情况下,我都不建议使用原始内存和realloc,但使用具有自己重新分配的std::vector,或使用std::array作为固定大小的缓冲区。

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

答案 1 :(得分:0)

方法2听起来更好,但是你的解析器可能会有很大的后果......即一旦找到你的特殊标记,在解析HTTP请求时处理非连续缓冲区可能最终比重新分配更昂贵或更复杂大缓冲区(方法1)。 Net-net:如果您的解析器很简单,请使用2,否则请使用1。