The nice thing about boost::asio is that it lets you do the traditional TCP stream logic as mentioned and as your code shows which is for great efficiency as well as letting you implement that type of logic easily with another API function called
async_read.
Using async_read and assuming you have a fixed header style protocol (which makes it extremely simple, the alternative is still doable just a little more logic work) you can instead just do this:
- Post header read (wait for it)
- Post data read (wait for it)
- Process complete packet
- Loop
So, first, you'd post a 3 byte read into a buffer, I use std::vector for my data buffers but boost does have an array I believe some people use instead. I use a vector because I have other code that uses a vector that I didn't want to convert to a boost array simply for the sake of doing the same thing using a different class. Anyways, async_read will read all the data you are requesting so you don't have to treat the data you are getting as a stream but rather as packet chunks.
Once you have the 3 bytes, you'd process the size and then post another read of that length. Here, you'd just resize the vector to 3 + destination size and make sure to pass the correct pointers to the buffer locations to write to async_read. There are some gotchas you have to watch out for though. Since your size field is only 2 bytes, a user can only allocate up to 65kb of memory, but if you had a larger field, you'd want to cap it so people can't crash your server by sending large sizes in the field! You still might want to limit it if your protocol won't ever use larger packets though just to be safe. Don't forget you need to handle 0 bytes as well so don't just post a read without checking the size before going on to the processing stage!
So now, when you determine you have the final packet stored, you can just process it. When you are done, clear the buffer and then post the next read of 3 bytes to wait for the next header. The boost:;asio chat example actually uses two different handlers to accomplish this, but I just use one in my code. Either works though; I just like having minimal code which boost lets me compared to alternative solutions of doing it by hand.
This approach scarifies efficiency at the expense of being
easy to implement and follow. You have well defined behavior and overall for a project on the scale you have mentioned in other threads, it should be just fine.
As I said in a reply to another of your threads, the learning curve here is mostly boost. You should still understand how TCP works, which it appears you do from this thread, so once you see how boost::asio simplifies the work, you can move on to writing more tailored code that can either be more efficient using async_read_some or easier to implement via async_read. For my light weight projects, I have been using this method I've talked about here and it's worked great. No more needing to track sliding buffers and trying to work with more data than I actually need!