Missing the first characters using boost::asio::streambuf

感情迁移 提交于 2019-12-06 13:38:39

boost::asio::async_read_until() can read any amount of characters to streambuf after \n. It then gives you bytes_transferred, which is count of characters in the first line (not necessarily the count of characters that were read to the buffer). See documentation.

As long as you keep your buffer variable intact, next boost::asio::async_read_until() will read characters first from the buffer and then from the socket.

It seems to me that you read a line from the buffer using getline(), which is correct. After that, you call

buff.consume(buff.size());

which clears the buffer, removing all information about the partial lines you may have received. The first complete line that you read has already been removed from the buffer by getline(), so the consume() call is unnecessary in any case.

Just removing the consume() call would not solve your problem, because you seem to use one buffer that is shared between all clients, and you would not know what partial data was from which client. A possible solution could be creating a list of buffers (one for each client), just like you have a list of sockets. Then boost::asio::async_read_until() and getline() would take care of handling the partial data, and you wouldn't have to think about that.

sehe

The other answer explains what went wrong.

However it can be a bit tricky to find out how to fix it.

Maybe you can find inspiration from a similar question I handled here:

Here, the OP was having trouble with basically the same thing: after reading his HTTP headers he would have "dropped" part of the body. So I added logic:

NOTE Again, it's important not to assume that the end-of-headers coincides with the packet boundary. Therefore, start read_body() with draining the available input already received.

std::shared_ptr<std::vector<char> > bufptr = std::make_shared<std::vector<char> >(nbuffer);

auto partial = std::copy(
        std::istreambuf_iterator<char>(&pThis->buff), {}, 
        bufptr->begin());

std::size_t already_received = std::distance(bufptr->begin(), partial);

assert(nbuffer >= already_received);
nbuffer -= already_received;

I think I fixed the issue. Just created a list of streambufs - a streambuf for each client. But I had to keep the consume() function, because otherwise the check if a given name already exists failed resulting in possibility to have several clients sharing the same name. Then messaging stopped working but I removed the locks in extract() and now everything appears to be all right.

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