Hi.
Now Im all confused. The asycn_write call back handler only return when all your buffer is sent.
Am I reading this wrong.
async_write function is used to asynchronously write a certain number of bytes of data to a stream. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true:
- All of the data in the supplied buffers has been written. That is, the bytes transferred is equal to the sum of the buffer sizes.
- An error occurred.
Does that not mean that the whole buffer is sent. Like wise read is the same the call back is not invoked until all the data is ready.
Here is my connection class the relevant parts
//------------------------------------------------------------------
// Asynchronously write a data structure to the socket.
//this uses the cPacket its allready serialized
//------------------------------------------------------------------
template <typename Handler>
void async_write(Handler handler, cPacket &t)
{
//copy the message to the buffer so we dont lose it
t.GetData(outbound_data_);
// Format the header.
std::ostringstream header_stream;
header_stream << std::setw(header_length)
<< std::hex << outbound_data_.size();
if (!header_stream || header_stream.str().size() != header_length)
{
// Something went wrong, inform the caller.
boost::system::error_code error(boost::asio::error::invalid_argument);
socket_->get_io_service().post(boost::bind(handler, error));
return;
}
outbound_header_ = header_stream.str();
// Write the serialized data to the socket. We use "gather-write" to send
// both the header and the data in a single write operation.
std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(boost::asio::buffer(outbound_header_));
buffers.push_back(boost::asio::buffer(outbound_data_));
boost::asio::async_write(*socket_, buffers, handler);
}//end async_write
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------
// Handle a completed read of a message header. The handler is passed using
// a tuple since boost::bind seems to have trouble binding a function object
// created using boost::bind as a parameter.
//------------------------------------------------------------------
template <typename Handler>
void handle_read_header(const boost::system::error_code& e,
cPacket &t, boost::tuple<Handler> handler)
{
if(e)
{
std::cout << "Error Client Read Header = " << e.message() << std::endl;
boost::get<0>(handler)(e);
}
else
{
// Determine the length of the serialized data.
std::istringstream is(std::string(inbound_header_, header_length));
std::size_t inbound_data_size = 0;
if (!(is >> std::hex >> inbound_data_size))
{
// Header doesn't seem to be valid. Inform the caller.
boost::system::error_code error(boost::asio::error::invalid_argument);
boost::get<0>(handler)(error);
return;
}
// Start an asynchronous call to receive the data.
inbound_data_.resize(inbound_data_size);
void (cConnection::*f)(const boost::system::error_code&, cPacket&, boost::tuple<Handler>) = &cConnection::handle_read_data< Handler>;
boost::asio::async_read(*socket_, boost::asio::buffer(inbound_data_),
boost::bind(f, this,
boost::asio::placeholders::error, boost::ref(t),
handler));
}
}//end handle_read_header
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Handle a completed read of message data.
template <typename Handler>
void handle_read_data(const boost::system::error_code& e,
cPacket &t, boost::tuple<Handler> handler)
{
if(e)
{
std::cout << "Error Client Read Data Block = " << e.message() << std::endl;
boost::get<0>(handler)(e);
}
else
{
// Extract the data structure from the data just received.
try
{
std::cout << " Client Read Data Block Size = " << inbound_data_.size() << std::endl;
std::string archive_data(&inbound_data_[0], inbound_data_.size());
t.Set(archive_data);//keep it serialized
//std::istringstream archive_stream(archive_data);
//boost::archive::text_iarchive archive(archive_stream);
//archive >> t;
}
catch (std::exception& e)
{
// Unable to decode data.
boost::system::error_code error(boost::asio::error::invalid_argument);
boost::get<0>(handler)(error);
return;
}
// Inform caller that data has been received ok.
boost::get<0>(handler)(e);
}
}//end handle_read_data
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
the drived class has the handle write
/// Handle completion of a write operation.
void handle_write(const boost::system::error_code& e, cConnection_ptr client)
{
std::stringstream ss;
//ss << "Server Handle Write Completed \n";
//global_stream_lock.lock();
//send the data to the client list box
//SendMessage(GlobalList, (UINT)LB_ADDSTRING , 0, (LPARAM) ss.str().c_str());
//global_stream_lock.unlock();
std::string ip;
std::string ipport;
client->GetIPAddress(ip);
client->GetIPAddressAndPort(ipport);
if(!e)// && read_msg_.decode_header())
{
//std::cout << "Server Sent All DATA" << std::endl;
ss.str("");
ss.clear();
ss << "SClient["<< ip << "]" << "Port[" << ipport << "]" << " Socket Has Sent All DATA";
global_stream_lock.lock();
//send the data to the client list box
SendMessage(GlobalList, (UINT)LB_ADDSTRING , 0, (LPARAM) ss.str().c_str());
global_stream_lock.unlock();
//we have sent the data now reset our flag
AtomicSendInprogress = false;
cPacket packet;
if(SendQueue.pop(packet))
{
//send this next message
AtomicSendInprogress = true;//so we don't mix the stream with a nother packet
async_write(boost::bind(&cSession::handle_write, this,boost::asio::placeholders::error, shared_from_this()),
packet);
}//end sending data
}
else
{
//there could be other messages when the first removes a client
//remove this client from the lobby its a dead client
Lobby.leave(shared_from_this());
}
}