12

到目前为止,我有这个代码示例:

...
int nbytes =0;
vector<unsigned char> buffer;
buffer.resize(5000);
nbytes = recv(socket, &buffer[0], buffer.size(),0);
//since I want to use buffer.size() to know data length in buffer I do
...
buffer.resize(nbytes);

是否有另一种方式,在不使用 resize() 两次的情况下知道缓冲区中的数据长度?因为不可能将数据接收到未调整为适当大小的向量中。根据 C++ STL 文档,我认为 reserve() 方法不进行分配。还有一个问题:使用这种技术是内存泄漏安全的吗?

4

5 回答 5

5

recv您无能为力,在通话之前您无法知道帖子的大小。

一些清理:

std::vector<unsigned char> buffer(5000);
int result = recv(socket, buffer.data(), buffer.size(), 0);
if (result != -1) {
   buffer.resize(result);
} else {
   // Handle error
}
于 2010-11-19T09:45:00.517 回答
3

这种技术是防泄漏的,非常干净且更可取。Usingstd::vector是在 C++ 中实现可变长度缓冲区的推荐方法。

如果您发现并非所有数据都适合向量 - 没问题,只需将其调整为更大的大小并传递已填充部分之后的部分的地址。

使用reserve()不是一个好主意 - 它不会影响size()返回的内容,因此您将失去便利并且可能不会获得任何优势。

于 2010-11-19T09:42:32.670 回答
1

这段代码很好。resize和之间的区别在于reserve,它resize改变了返回的值size(并且实际上创建了新的默认初始化对象),而reserve没有(它只分配更多的内存)。

根据您处理数据的方式,您可以省略第二resize个,并使用如下循环执行:

for (vector<unsigned char>::iterator it = buffer.begin(); 
     it != buffer.begin() + nbytes; 
     it++) 
{
    // process each byte
}

因此,您可以只读取实际写入的数据,而忽略其余部分。这意味着您只需设置一次向量的大小,然后永远不要更改它。一般来说,只要你只使用迭代器,就不需要调整向量的大小,因为有效的数据范围总是[buffer.begin(), buffer.begin() + nbytes).

于 2010-11-19T09:42:13.223 回答
1

我不相信[更优雅的方式?]。从根本上说,您需要在缓冲区中有足够多的字符到recv多个字节;然后,一旦您阅读了它们,如果您希望缓冲区仅包含接收到的字节,则需要向下调整大小。你所展示的可能与我处理事情的方式相似。

你是对的,这reserve还不够。您不能写入不存在且仅预先为它们分配存储的元素。

于 2010-11-19T09:43:37.687 回答
0

使用 TCP 时有一种更优雅的方式:使用消息头。
您知道标头的(固定)大小,因此您可以在固定大小的缓冲区中读取它。
在标头内部,有一个消息大小,因此您可以使用它来分配缓冲区并读取标头中指定的字节数。

请注意,使用它,您可能需要一些特殊情况的技术,例如对长消息进行分段。

于 2010-11-19T09:57:50.913 回答