I have a very simple method, with the purpose of responding to an incoming message, and then closing the connection:
void respond ( const std::string message )
{
std::string str = "<?xml version=\"1.0\"?>";
Controller & controller = Controller::Singleton();
if ( auto m = handleNewMessage( _message ) )
{
auto reply = controller.FIFO( m );
str.append( reply );
}
else
str.append ( "<Error/>" );
std::size_t bytes = str.size() * sizeof( std::string::value_type );
std::cout << "Reply bytesize " << bytes << std::endl;
boost::asio::async_write(
socket_,
boost::asio::buffer( str ),
boost::bind(
&TCPConnection::handle_write,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
));
}
void handle_write ( const boost::system::error_code & error, size_t bytes_transferred )
{
if ( error )
{
std::cerr << "handle_write Error: " << error.message() << std::endl;
std::cerr << "handle_write Bytes sent: " << bytes_transferred << std::endl;
}
else
{
std::cerr << "handle_write Bytes sent: " << bytes_transferred << std::endl;
socket_.close();
}
}
I know the problem is that boost::asio::async_write does not complete the writing operation, because the output from the above operations is:
Reply bytesize: 354275
handle_write Bytes sent: 65536
Implying that the maximum buffer size (65536) was not enough to write the data?
Searching around Stack Overflow, I discovered that my problem is that the buffer created by the method:
boost::asio::buffer( str )
goes out of scope before the operation has a chance to finish sending all the data.
It seems like I can't use a boost::asio::mutable_buffer, but only a boost::asio::streambuf
Furthermore and more importantly, a second error complains about the actual boost::asio::async_write being passed a boost::asio::const_buffer OR boost::asio::mutable_buffer:
/usr/include/boost/asio/detail/consuming_buffers.hpp:164:5: error: no type named ‘const_iterator’ in ‘class boost::asio::mutable_buffer’
const_iterator;
^
/usr/include/boost/asio/detail/consuming_buffers.hpp:261:36: error: no type named ‘const_iterator’ in ‘class boost::asio::mutable_buffer’
typename Buffers::const_iterator begin_remainder_;
So I am left with only one choice: To use a boost::asio::streambuf
I've tried using:
boost::asio::streambuf _out_buffer;
As a class member, and then made method respond:
std::ostream os( &_out_buffer );
os << str;
boost::asio::async_write(
socket_,
_out_buffer,
boost::asio::transfer_exactly( bytes ),
boost::bind(
&TCPConnection::handle_write,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
));
However, although I get no errors, not the entire data is sent! So, I am guessing, not the entire string is written into the streambuf?
Alternatively, I would love to know what is the most elegant way to write using boost::asio::async_write, data that is larger than 65536 bytes!