使用recv()和vector <unsigned char =“”> </unsigned>的更优雅的方法

时间:2010-11-19 09:39:38

标签: c++ stl vector recv

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

...
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()方法不进行分配。另一个问题是:使用这种技术是内存泄漏安全吗?

5 个答案:

答案 0 :(得分:4)

您无法做多少,在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
}

答案 1 :(得分:3)

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

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

使用reserve()不是一个好主意 - 它不会影响size()返回的内容,因此您将失去方便,可能不会有任何好处。

答案 2 :(得分:1)

这段代码很好。 resizereserve之间的区别在于,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)

答案 3 :(得分:1)

我不相信[更优雅的方式?]。从根本上说,你需要在缓冲区中有足够多的字符来recv多个字节;一旦你读完它们,如果你想让缓冲区只包含接收的字节,你需要向下调整大小。你所展示的内容可能类似于我的处理方式。

你是正确的reserve是不够的。您不能写入不存在的元素,并且事先只为它们分配了存储空间。

答案 4 :(得分:0)

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

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