A more elegant way to use recv() and vector<unsigned char>

半城伤御伤魂 提交于 2019-12-18 13:09:19

问题


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 ?


回答1:


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 what size() returns, so you will lose convenience and likely will gain no advantages.




回答2:


There is not much you can do, you cannot know the post size before the recv call.

Some cleanup:

std::vector<unsigned char> buffer(5000);
int result = recv(socket, buffer.data(), buffer.size(), 0);
if (result != -1) {
   buffer.resize(result);
} else {
   // Handle error
}



回答3:


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.




回答4:


This code is fine. The difference between resize and reserve is, that resize changes the value returned by size (and actually creates new default initialized objects), whereas reserve 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:

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

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).




回答5:


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.



来源:https://stackoverflow.com/questions/4223711/a-more-elegant-way-to-use-recv-and-vectorunsigned-char

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!