Boost asio async_read_some reading only part of the data

I have a C ++ server that uses boost :: asio for read / write operations - writing messages works fine - but for some reason I can't get the reading to work

The message I send him 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 constantly see such things. reading is often interrupted 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 launch 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 launch 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 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)); } } 

following variables

 const int READ_DATA_BUFFER_LENGTH = 1024; class AbstractSession { protected: uint16_t _read_data_buffer[READ_DATA_BUFFER_LENGTH]; ... 

There is one thing: I use the same IO service to record messages when they are received (the server speaks with the old interface and sends messages that it receives to all clients), and to read messages from clients, can I use the same io service for both to make this happen?

Any thoughts on what I should do to fix this?

+4
source share
1 answer

Your code does what it should do - it reads as much data as possible. This is why the async_read_some function name ends with "some" - it reads "some" bytes and does not promise to do more. The documentation also says the following:

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

This is similar to your case if you do not rework your receiver to handle partial readings.

+4
source

All Articles