简体   繁体   中英

boost asio async_read_some reading only pieces of data

i have a c++ server which is using boost::asio to do read/write operations - writing out the messages works fine - yet for some reason i cannot get the read to work

the message i am sending to it from the client is 15 16 bit unsigned shorts - my test message is this:

1, 34, 7, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0

now on the server i'm seeing things like this constantly. the read is often broken up and/or multiplied by 256

this is one run sending it twice

reading length = 8: [1 34 7 0 0 0 0 0]
reading length = 3: [1024 0 0]
reading length = 3: [0 0 0]
reading length = 8: [1 34 7 0 0 0 0 0]
reading length = 6: [1024 0 0 0 0 0]

this is the second run sending it twice

reading length = 8: [1 34 7 0 0 0 0 0]
reading length = 6: [1024 0 0 0 0 0]
reading length = 6: [1 34 7 0 0 0]
reading length = 1: [0] 
reading length = 0: []
reading length = 0: []
reading length = 2: [0 0]
reading length = 2: [0 0]
reading length = 1: [0]

this is the third run sending it once (i don't know what happened here)

reading length = 14: [256 8704 1792 0 0 0 0 0 1024 0 0 0 0 0]

Here is the actual server read code

void Session::start(void) {
  msg_interface->add_msg_listener(this);
  _socket.async_read_some(
    boost::asio::buffer(_read_data_buffer, READ_DATA_BUFFER_LENGTH),
    boost::bind(&Session::handle_read, this, boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));
}

void Session::handle_read(const boost::system::error_code& error, std::size_t bytes_transferred) {
  if (error) {
    msg_interface->remove_msg_listener(this);
    delete this;
  } else {
    if (bytes_transferred != 0) {
      // print what we've received
      const int length = bytes_transferred / sizeof(uint16_t);
      std::cout << "reading length = " << length << ": [";
      for (int i = 0; i < length; i++) {
        const uint16_t data = ntohs(_read_data_buffer[i]);
        std::cout << data;
        if (i != length - 1) {
          std::cout << " ";
        }
      }
      std::cout << "]" << std::endl;
    }
    _socket.async_read_some(
      boost::asio::buffer(_read_data_buffer, READ_DATA_BUFFER_LENGTH),
      boost::bind(&Session::handle_read, this, boost::asio::placeholders::error,
        boost::asio::placeholders::bytes_transferred));
  }
}

the variables are as follows

const int READ_DATA_BUFFER_LENGTH = 1024;

class AbstractSession {
protected:
  uint16_t _read_data_buffer[READ_DATA_BUFFER_LENGTH];
...

There is one thing - i am using the same IO service to write messages when they are received (the server is talking to an old interface and sends out the messages it receives to all the clients) and to read messages from the clients. could using the same io service for both cause this to happen?

Any thoughts on what i should do to fix this?

Your code does what it is supposed to do - it reads as much data as it can. This is why the function async_read_some name ends with "some" - it reads "some" bytes and does not promise to do more than that. Documentation also says the following:

Consider using the async_read function if you need to ensure that the requested amount of data is read before the asynchronous operation completes.

Which seems like your case unless you re-work your receiver to handle partial reads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM