user2538425
user2538425

Reputation: 65

boost read_some function lost data

I'm implementing a tcp server with boost asio library. In the server, I use asio::async_read_some to get data, and use asio::write to write data. The server code is something like that.

std::array<char, kBufferSize> buffer_;
std::string ProcessMessage(const std::string& s) {
   if (s == "msg1") return "resp1";
   if (s == "msg2") return "resp2";
   return "";
}
void HandleRead(const boost::system::error_code& ec, size_t size) {
  std::string message(buffer_.data(), size);
  std::string resp = ProcessMessage(message);
  if (!resp.empty()) {
    asio::write(socket, boost::asio::buffer(message), WriteCallback);
  }
  socket.async_read_some(boost::asio::buffer(buffer_));
}

Then I write a client to test the server, the code is something like

void MessageCallback(const boost::system::error_code& ec, size_t size) {
   std::cout << string(buffer_.data(), size) << std::endl;
}
//Init socket
asio::write(socket, boost::asio::buffer("msg1"));
socket.read_some(boost::asio::buffer(buffer_), MessageCallback);
// Or async_read
//socket.async_read_some(boost::asio::buffer(buffer_), MessageCallback);
asio::write(socket, boost::asio::buffer("msg1"));
socket.read_some(boost::asio::buffer(buffer_), MessageCallback);
// Or async_read
//socket.async_read_some(boost::asio::buffer(buffer_), MessageCallback);

If I run the client, the code will be waiting at second read_some, and output is:resp1.

If I remove the first read_some, the ouput is resp1resp2, that means the server done the right thing.

It seems the first read_some EAT the second response but don't give the response to MessageCallback function.

I've read the quesion at What is a message boundary?, I think if this problem is a "Message Boundary" problem, the second read_some should print something as the first read_some only get part of stream from the tcp socket.

How can I solve this problem?

UPDATE: I've try to change the size of client buffer to 4, that output will be:

resp
resp

It seems the read_some function will do a little more than read from the socket, I'll read the boost code to find out is that true.

Upvotes: 1

Views: 3384

Answers (1)

Sam Miller
Sam Miller

Reputation: 24174

The async_read_some() member function is very likely not doing what you intend, pay special attention to the Remarks section of the documentation

The read operation may not read all of the requested number of bytes. Consider using the async_read function if you need to ensure that the requested amount of data is read before the asynchronous operation completes.

Note that async_read() free function does offer the guarantee that you are looking for

This operation is implemented in terms of zero or more calls to the stream's async_read_some function, and is known as a composed operation. The program must ensure that the stream performs no other read operations (such as async_read, the stream's async_read_some function, or any other composed operations that perform reads) until this operation completes.

Upvotes: 2

Related Questions