使用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() 方法不进行分配。还有一个问题:使用这种技术是内存泄漏安全的吗?
So far, I have this code sample:
...
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);
Is it some another way, to know data length in buffer without using resize() twice? Because it is not possible to receive data into vector that is not resized to proper size. I think reserve() method don't do allocation, according to the C++ STL documentation. And another question: is using this kind of technique is memory leak-safe ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您无能为力,在
recv
调用之前您无法知道帖子大小。一些清理:
There is not much you can do, you cannot know the post size before the
recv
call.Some cleanup:
这种技术是安全的、非常干净的并且是优选的。使用 std::vector 是在 C++ 中实现可变长度缓冲区的推荐方法。
如果您发现并非所有数据都适合向量 - 没问题,只需将其大小调整为更大的大小并传递已填充部分后面的部分的地址。
使用
reserve()
并不是一个好主意 - 它不会影响size()
返回的内容,因此您将失去便利,并且可能不会获得任何优势。This technique is leak-safe, quite clean and preferable. Using
std::vector
is the recommended way of implementing a variable-length buffer in C++.If you find that not all data fits into the vector - no problem, just resize it to bigger size and pass the address of the section that follows the already-filled part.
Using
reserve()
is not a very good idea - it doesn't affect whatsize()
returns, so you will lose convenience and likely will gain no advantages.这段代码很好。
resize
和reserve
之间的区别在于,resize
更改了size
返回的值(并且实际上创建了新的默认值)初始化的对象),而reserve
则不然(它只会分配更多内存)。根据处理数据的方式,您可以省略第二个
resize
,并使用如下循环进行操作:因此,您可以只读取实际写入的数据,而忽略其余部分。这意味着您只需设置一次向量的大小,然后就永远不会更改它。一般来说,只要您只使用迭代器,就不需要调整向量的大小,因为有效数据范围始终是
[buffer.begin(), buffer.begin() + nbytes)
。This code is fine. The difference between
resize
andreserve
is, thatresize
changes the value returned bysize
(and actually creates new default initialized objects), whereasreserve
does not (it only allocates more memory).Depending on how you process the data, you can leave the second
resize
out, and do it with a loop like this:Thus you can just read the data that was actually written, and ignore the rest. This means you would only set the size of the vector once, and then never change it. In general, as long you only work with iterators, there is no need to resize the vector, as the valid data range will always be
[buffer.begin(), buffer.begin() + nbytes)
.我不这么认为[更优雅的方式?]。从根本上来说,缓冲区中需要有足够多的字符才能
recv
许多字节;然后,一旦您读取它们,如果您希望缓冲区仅包含接收到的字节,则需要向下调整大小。你所展示的可能与我处理事情的方式相似。您是对的,
reserve
是不够的。您无法写入不存在且仅预先为其分配存储空间的元素。I don't believe so [a more elegant way?]. Fundamentally, you need to have more than enough characters in the buffer to
recv
many bytes; then once you've read them, if you want the buffer to only contain the received bytes you need to resize downwards. What you've shown is probably similar to how I would approach things.You are correct that
reserve
is not sufficient. You cannot write to elements that don't exist and have only had storage allocated for them in advance.使用 TCP 时有一种更优雅的方法:使用消息头。
您知道标头的(固定)大小,因此您可以在固定大小的缓冲区中读取它。
在标头内,有一个消息大小,因此您可以使用它来分配缓冲区并读取标头中指定的字节数。
请注意,使用此功能时,您可能需要一些针对特殊情况的技术,例如长消息的分段。
There is a more elegant way when using TCP: use a message header.
You know the (fixed) size of the header, so you can read this in a fixed size buffer.
Inside the header, there is a message size, so you can use that to allocate your buffer and read the number of bytes as specified in the header.
Mind you that using this, you might need some techniques for secial cases like fragmenting for long messages.