When I do request_stream << message; I'm putting the content of message into the variable request. The variable request is a private variable that belongs to the Client class. As I said before, the asynchronous functions are called first (the constructor calls async_resolve, which calls async_connect, which calls async_write, which calls async_read). Only then is the send function called from the main function.
Ok, now it's more clear. Lets see what happens, step by step: 1) you create Client object: async_resolve is queued to the io_service object, which is not running yet 2) you call Client::Send - io_service::run is called (note: the caller of Client::Send() will now wait until (8) ) 3) io_service starts dispatching the pending async_resolve request 4) handler of async_resolve is called, which in turn queues async_connect 5) handler of async_connect is called - async_write is queued; at this point your buffer is consumed and sent to the peer 6) handler of async_write is called - async_read is queued 7) etc... until at some stage read/write chain ends, i.e. all handlers are done and no more i/o request is queued 8) only *now*, when there's no more work, io_service::run exits, and so does your Send() function - the caller may now continue with his stuff. Actually, you got synchronous i/o, but I guess this wasn't your intent, was it? If it was, you could just use simple synchronous functions: resolve(); connect(); write(); read() - much simpler and with the same effect. What you could do to take an advantage of the async.i/o is to run the io_service in some other thread, like in this example: http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/example/chat/chat_c...