Pages

Getting the file size

In the previous post, as a way to have a first glimpse of the Boost Filesystem library, we wrote a rough but usable function that used boost::filesystem::file_size().

Let's going on pretending that we developed that function as answer to a client request, who now asks for an improvement, since he would like to have a better output. He could accept to be notified of an exception if really happens something unexpected (like: the unit specified on the file system does not exist), but in case the passed filename refers to a non existing object in the file system, or such an object is not a regular file (for which it has actually sense retrieving the size) he wants to be notified in a more gentle way.

Not a big issue, we just have to use a few other Boost Filesystem functions.

Here is the code for the improved function:
void fileSize2(boost::filesystem::path filename)
{
try
{
if(!boost::filesystem::exists(filename)) // 1.
{
std::cout << filename << " does not exist" << std::endl;
return;
}

if(boost::filesystem::is_directory(filename)) // 2.
{
std::cout << filename << " is a directory" << std::endl;
return;
}

if(!boost::filesystem::is_regular_file(filename)) // 3.
{
std::cout << filename << " is not a regular file" << std::endl;
return;
}

std::cout << filename << " size: "
<< boost::filesystem::file_size(filename) << std::endl; // 4.
}
catch(const boost::filesystem::filesystem_error& ex) // 5.
{
std::cout << ex.what() << std::endl;
}
}

1. Firstly we check if the passed name refers to an object in the file system. Notice that usually a Boost Filesystem functions, like exists() here, throws a filesystem_error exception if anything weird happens. Alternatively, when for any reason we don't want to (or we can't) use the try-catch structure, we could call a function overload that returns an error code.
2. Secondly, since does not make much sense to check the size of a directory, we check it using the is_directory() function.
3. Thirdly, we consider that there could be more than normal files and directories in a file system. Here we trap the case in which the passed file name is associated with "something" that in our current environment is not recognized as a "regular" file.
4. Finally we call the Boost Filesystem function to get the file size.
5. Any unexpected error from the previous calls to Boost Filesystem functions is trapped here, giving back to the user the message stored in the exception.

The code in this post is based on an example that you can find in the official boost filesystem tutorial. For more background information, you could have a look at the Boost filesystem version 3 home page.

Go to the full post

The Boost Filesystem library

Writing a C++ function that prints to standard output the size of a file given its filename, is a more complicated job than one could expect.

This is because the C++ standard does not make available (yet) any library to shield the different approaches taken by different operating system to the file system, and so the programmers have to directly take care of the system's low level details.

Alternatively, we could use the Boost Filesystem library. By the way, this library is a candidate to be included in Technical Report 2, and so we could expect that something close to it would be eventually included in the standard.

The typical issues we have to tackle when writing code that has to do with file system are:

Are the file names written accordingly Windows or UNIX conventions (or both)?

Is the passed filename correct? I mean, does it refer to what could be an object in the referred file system?

Does that file actually exists?

Accessing to a file system is always a dangerous matter: how we could avoid the application to crash in case of an unforeseen problem?

The Boost::filesystem answer to these questions using a custom class for storing the filename and throwing exceptions (or returning an error code, if for any reason we don't want our code to use the exception facility) in case of errors.

Let see as example a possible implementation for the function we said above: it gets as input a filename, and it prints to standard console it length:
#include <iostream>
#include <boost/filesystem.hpp>

// ...

void fileSize(boost::filesystem::path filename)
{
try
{
std::cout << filename << " size: "
<< boost::filesystem::file_size(filename) << std::endl;
}
catch(const boost::filesystem::filesystem_error& ex)
{
std::cout << ex.what() << std::endl;
}
}

Amazingly concise and effective, I'd say. We try to call the Boost Filesystem file_size() function, if it succeeds, it returns a uintmax_t (the biggest unsigned integer type available for the current platform), otherwise it throws an exception.

Here is a few test calls I performed for this function:
fileSize(argv[0]); // 1.

std::string s("/dev/pl.sql"); // 2.
fileSize(s);

fileSize("/dev"); // 3.

fileSize("W:\\not\\existing.com"); // 4.

1. We pass to our function the first argument coming from the environment to the main() function, that is the filename used to invoke the application. Being compiled for Windows, it is in that format.
2. We can pass to our function C and C++ strings. Notice that here we are using the UNIX convention (forward slashes)
3. On the current drive I have a directory named in this way. Asking for the size of a directory leads to an exception.
4. There is no "W" drive on my environment. So here I expect another exception.

The example code is based on what you can find in the official boost filesystem tutorial. For more background information, you could have a look at the Boost filesystem version 3 home page.

Go to the full post

Using enable_shared_from_this

In the previous post we have seen where the need for enable_shared_from_this arise. Now we have a look at how actually use it.

To put it simply, our class should derive from the template class enable_shared_from_this and should use the method shared_from_this() to create a shared_ptr, when that make sense.

Here too I explicitly refer to the standard implementation (std), if your compiler does not support it yet, you can use Boost instead, just change the namespace to boost and refer to the proper files.

We declare a class in this way:
class SomethingElse : public std::enable_shared_from_this<SomethingElse>
{
// ...
};

So that we can use the public method shared_from_this() to create a shared_ptr to SomethingElse. In case it makes no sense calling shared_from_this(), but we still call it, the method throws an exception, to let us know we are in trouble. This could look like a nuisance, but actually it's a huge step ahead with respect to having an undefined behaviour.

Have a look at the definition of a simple public method for our class:
void aMethod()
{
try
{
std::shared_ptr<SomethingElse> sp = shared_from_this(); // 1.
if(sp.use_count() > 1)
std::cout << "As expected" << std::endl;
}
catch(std::exception& ex) // 2.
{
std::cout << "Exception: " << ex.what() << std::endl;
std::cout << "You should use this method only from a shared_ptr!" << std::endl;
}
}

1. Here we create a shared_ptr using shared_from_this(), we don't have much to do with it here, actually, so we just check its internal count, that we expect to be more than one, since we assume that "this" was already owned by another shared_ptr. But what if our assuption is wrong?
2. If we try to call shared_from_this(), and no shared_ptr is already owning "this", we'll end up here. Since aMethod() doesn't have much to do, we simply log to the output console a message.

Now we can correctly call aMethod() in this way:
std::shared_ptr<SomethingElse> spse(new SomethingElse);
spse->aMethod();

It is still a mistake calling aMethod() from an object on the stack, or in the heap but not associated to a shared_ptr. But at least we could design our code to avoid crashes even though the class user call it anyway:
SomethingElse se;
se.aMethod(); // error message printed to cout

SomethingElse* pse = new SomethingElse;
pse->aMethod();
delete pse; // error message printed to cout

Last but not least, we should remember that makes no sense calling shared_from_this() where "this" is not available. Most noticeable, that is the case of the constructor. Look at this code:
class SomethingWrong : public std::enable_shared_from_this<SomethingWrong>
{
public:
SomethingWrong()
{
try
{
std::shared_ptr<SomethingWrong> sp = shared_from_this();
if(sp.use_count() > 1)
std::cout << "Not expected anymore" << std::endl;
}
catch(std::exception& ex)
{
std::cout << "Expected exception: " << ex.what() << std::endl;
}
}
};

The SomethingWrong usage of shared_from_this() is the same of SomethingElse's. But here we are trying to use "this" before "this" would be actually available. So, even if we'll try to use our class in a way that we would have expected to be corrected:
std::shared_ptr<SomethingWrong> spse(new SomethingWrong);
we always and up with having a trapped exception in the object ctor.

Go to the full post

Need for enable_shared_from_this

I'm about to call a function that requires as parameter a shareable pointer to an object of a given class, but the fact is that I do not have such a beast at hand, just a raw pointer. That is quite a nuisance, because normally there is no way to go from a raw pointer to a shared pointer that already owns it.

But if our C++ compiler is 0x compliant, or if we can use the Boost libraries, we have access to a reasonable simple mechanism to overcome this issue: just derive the class we are interested in from enable_shared_from_this and then use shared_from_this() to create the required shared_ptr.

Actually, things are not so simple. There are a few details we should be aware of. But, first things first, let's see what happens if we don't rely on enable_shared_from_this.

Given a class, that I have imaginatively called Something, the preferred way to create a shared pointer to an object is:
std::shared_ptr<Something> sp1(new Something);
In this way we stress the fact that we don't expect any part of the subsequent code to directly use the raw pointer. But this is just an hint. We can perform the same operation in two steps
Something* ps = new Something;
std::shared_ptr<Something> sp(ps);
Besides, given a shared pointer we can always extract its raw pointer - even though that is not often a good idea - using the shared_ptr::get() method.

In any case, typically the issue arises because we are in a Something (I mean, our class) method and we want to use a shared pointer to "this" object. A (bad) idea would be to create on the fly a shared pointer from "this":
std::shared_ptr<Something> Something::badIdea() { return std::shared_ptr<Something>(this); }
And using the resulting smart pointer:
void Something::aMethod()
{
std::shared_ptr<Something> spBad = this->badIdea();
if(spBad.use_count() == 1)
std::cout << "Trouble!" << std::endl;
}

A conspicuously bad idea, and would lead to a nightmarish behaviour of our code.

We would expect to use that code in a context like:
std::shared_ptr<Something> sp1(new Something);
sp1->aMethod();

But this is plain asking for trouble. We ends up having two unrelated shared_ptr, each of them rightfully thinking to have the resource ownership. Both of them, when exiting their respective scope, would call delete on the raw pointer, and that means undefined (usually catastrophical) behavior.

So, we can't use aMethod() from a shared_ptr, that make it completely useless, since we designed it thinking exactly for that scenario. But look at this code:
Something* ps = new Something;
ps->aMethod();

It looks kind of weird. There is no call to delete ps, and aMethod() actually behaves like a dtor, making ps invalid after its call. So, if we want to avoid disasters we should heavily comment any usage of aMethod() or - better - avoid writing code like that.

Even worse, the user could call aMethod from an object on the stack:
Something s;
s.aMethod();

Calling delete for an object allocated on the stack is pure nonsense, but in aMethod() we create a shared_ptr from "this", implicitly assuming it refers to a memory location on the heap, with all the (terrible) consequences of the case.

So, definitely it is not a good idea using that approach. We should instead enhance our class, providing a way of keeping track of an eventual related shared_ptr, so that we can refer to it when we create another shared_ptr instance for the same object on the heap. That is the task for which enable_shared_from_this has been created, and in the next post we see how to use it.

Go to the full post

To post or to dispatch?

We have already seen how to use the ASIO I/O Service post() method to run tasks concurrently. Actually, we could use another io_service method to get almost the same behavior: dispatch().

The subtle difference is that dispatch() could even execute directly the passed function, where post() always request to io_service to run it.

An example should clarify the matter.

[A Japanese translation of this post is available on the Faith and Brave C++ blog]

I slightly modify the original example, making it probably less immediate. Please, refer to it if you are looking for something less contrived. Now the main function of the application starts three threads, each of them running on the io_service.run() function. Then we ask the user if he wants to run a new function, or he wants to terminate the application. Finally we cleanup and terminate:
std::cout << "Main thread: " << boost::this_thread::get_id() <<  std::endl;

boost::asio::io_service ios; // 1
boost::asio::io_service::work work(ios); // 2

size_t count = 3;
boost::thread_group threads;
for(size_t i = 0; i < count; ++i)
  threads.create_thread(boost::bind(&boost::asio::io_service::run, &ios));

while(startAFunction())
  ios.post(boost::bind(fA, boost::ref(ios))); // 3

std::cout << "Stopping ASIO I/O Service ..." << std::endl;
ios.stop();
threads.join_all();
std::cout << "All threads terminated" << std::endl;
1. Instantiate a io_service object.
2. Try to comment this line: if you do it, the io_service won't have anything to run when you start the application up, so all the run() calls would happily terminate before we could submit to them anything to do.
3. We post() the function address of fA(), and a reference to ios, that would be passed to fA().

The very rough input function is here:
bool startAFunction()
{
  std::cout << "Enter a non-empty string to run A function" << std::endl;

  std::string input;
  getline(std::cin, input);
  return input.length() == 0 ? false : true;
}
If the user just press enter, the function returns false, otherwise it returns true.

And here is the function called by the main function:
void fA(boost::asio::io_service& ios)
{
  static int selector = 0;
  std::cout << boost::this_thread::get_id()
    << " starting A function" << std::endl;
  boost::this_thread::sleep(boost::posix_time::seconds(3));
  if(++selector % 2) // 1
  {
    std::cout << boost::this_thread::get_id()
      << " dispatching" <<  std::endl;
    ios.dispatch(fB);
  }
  else // 2
  {
    std::cout << boost::this_thread::get_id()
      << " posting" <<  std::endl;
    ios.post(fB);
  }
  std::cout << boost::this_thread::get_id()
    << " exiting A function" << std::endl;
}
1. The first time fA() is called, it dispatch() to the io_service a request of execution for another function, fB(), that we'll see next.
2. Here we see the alternative behavior, calling post().

The internally called function is not very interesting, at least in my implementation:
void fB()
{
  boost::this_thread::sleep(boost::posix_time::seconds(1));
  std::cout << boost::this_thread::get_id()
    << " running B function" << std::endl;
}
Running the application we'll see the difference between posting and dispatching. Since it could do it, dispatch() would execute fB() directly, so we'll see it runs in the current thread, and synchronously. On the other side, post() would ask to io_service to do the job, asynchronously in another thread, and it immediately returns the control to the caller.

Actually, in this example it doesn't make much sense using dispatch(), we could have called directly fB() saving some overhead.

Go to the full post

Running io_service in another thread

In the previous ASIO examples I have used the simple strategy of creating an ASIO I/O Service object; creating and initializing one or more I/O Object (in the last post, for instance, we created a bunch of deadline_timers); and finally calling run() on the I/O Service object.

This is OK for demonstrating the I/O Objects capabilities, but it is not the most commonly used strategy in a real world application, since io_service::run() is a synchronous call so, if we call it in our main thread, we get the unpleasant result of getting stuck there waiting for the I/O Service to terminate its job.

Usually we'd like to let another thread be stuck on io_service::run() and keep the main thread free to do more interesting stuff.

For instance our main thread could prompt the user for interrupting the execution. Admittedly not the most exciting task a main thread could do, but better than just sitting and waiting.

It is easy to adapt our code to this model, here is a basic schema in five steps:
// 1
boost::asio::io_service ios;

// 2 
// boost::asio::deadline_timer dt1 = boost::asio::deadline_timer(ios);
// ...

// 3
boost::thread bt(boost::bind(&boost::asio::io_service::run, &ios));

// 4
std::cout << "Press enter to terminate whenever you want!" << std::endl;
std::string request;
std::getline(std::cin, request);

// 5
ios.stop();
1. As usual, the first thing to do is creating an I/O Service object.
2. Then we set our I/O main job, for instance we could create one or more deadline_timers.
3. Here is the big change: the run() method of the ios object is called in another thread.
4. So the main thread is free to do whatever it wants. Here it just tells the user it is ready to terminate the execution.
5. When the user asks to terminate, we should ensure our I/O Service object leaves in a clean state, this is the reason for calling io_service::stop(), that takes care of cleanup the I/O Service task list before terminating.

Go to the full post

Many deadline_timers

We have seen that using a single ASIO deadline_timer is easy, even though, as we have seen when we were talking about canceling a scheduled deadline_timer there are a few details that we have to consider carefully.

Working with a collection of deadline_timers does not add much more complexity, but it is worthy to have a look at an example, just to clarify a few details.

We want to give the users a way of printing strings (as many as they want) each of them in a specified moment. Here we are not interested in how these data are provided to the application, let's just fake the input using this function:
typedef std::pair<int, std::string> Job; // 1.
typedef std::vector<Job> Jobs;

Jobs createJobCollection()
{
Jobs jobs;

jobs.push_back(std::make_pair(4, "Do something"));
jobs.push_back(std::make_pair(2, "Say hallo"));
jobs.push_back(std::make_pair(5, "Say goodbye"));
jobs.push_back(std::make_pair(3, "Turn off the radio"));

return jobs; // 2.
}

1. Our job is actually a pair consisting in a delay an the string we want to output.
2. Your STL implementation should be smart enough to optimize this return statement using the RValue semantic, if not, you could explicitely use std::move() to avoid the overhead of meaningless copies.

To manage the deadline_timer collection execution I'm going to use a specific class, JobLauncher. Here is its declaration:
typedef boost::shared_ptr<boost::asio::deadline_timer> SmartDT; // 1.
class JobLauncher
{
private:
boost::asio::io_service ios_; // 2.
std::vector<SmartDT> dts_;
public:
void add(Jobs& jobs);
void run() { ios_.run(); }
};

1. deadline_timer is a non-copyable class, but we want to have a STL collection of them. So we use smart pointers instead.
2. Remember that the order in which member variables are listed in a class declaration is the order used by the compiler to construct them in memory (and the reverse order used for destruct them). So we don't have to do anything more than writing the two data member in the correct order to ensure the relation between ASIO I/O Service and its associated Deadline Timers be enforced. On the other side, if we want to have a spectacular and unexpected crash, we could just invert these two lines.

We still have to define one function:
void JobLauncher::add(Jobs& jobs)
{
std::for_each(jobs.begin(), jobs.end(), // 1.
[&](Job j) // 2.
{
SmartDT dt(new boost::asio::deadline_timer(ios_)); // 3.

dt->expires_from_now(boost::posix_time::seconds(j.first));
dt->async_wait(boost::bind(&doJob, _1, j.second));
dts_.push_back(dt);
});
}

1. For each element in the passed collection of jobs we have to add a deadline timer to the member collection. We could do that in a number of ways. For instance we could use a STL standard algorithm for_each associated with a lambda function. There is another post where I chat about for each and alternatives.
2. We need to access a couple of variable outside the lambda scope, the ampersand in the lambda introducer (AKA capture clause - the open/close square brackets) says that we want to access them by reference. Actually, since here we are interested to member variable, that are mediate by "this" pointer, we could have used the equal sign instead, that means use the variable by copy.
3. A smart pointer for deadline_timer is created - notice that references to the member ASIO I/O Service.

And here is a simple tester:
Jobs jobs = createJobCollection();
JobLauncher jl;
jl.add(jobs);
jl.run();

Go to the full post

Canceling a deadline_timer

We have already seen how to set an ASIO deadline_timer. No big deal, actually. It's just a matter of specifying when the timer should expire and what to do at that moment. Here we are about to expand a bit this topic, seeing how we could cancel the request we made.

The final result of setting a Deadline Timer is a call to an action specified by the user. In the previous example we used a functor. Here we use instead a free function:
void doJob(const boost::system::error_code& ec, const char* msg) // 1.
{
if(!ec) // 2.
{
std::cout << "Message: " << msg << std::endl;
return;
}

if(ec == boost::asio::error::operation_aborted) // 3.
std::cout << "Never mind" << std::endl;
else
std::cout << ec.message() << std::endl;
}

1. The function must have an error_code among its parameters, but there could be more. Here we want a c-string to be passed too.
2. If the timeout expired correctly, we output the passed c-string to the console.
3. If the user canceled the timer, ASIO would signal the fact calling our function with error code set to operation_aborted.

Using ASIO I/O Service

As usual, we are going to run an ASIO I/O service object that would take care of orchestrating the execution details on our behalf:
boost::asio::io_service ios;

// the specific code would go here

ios.run();

Normal usage

Usually we would do something like that:
boost::asio::deadline_timer dt1 = boost::asio::deadline_timer(ios); // 1.
dt1.expires_from_now(boost::posix_time::seconds(1)); // 2.
dt1.async_wait(boost::bind(&doJob, _1, "Just say hello")); // 3.

1. Create a Deadline Timer object associated to our I/O Service.
2. Specify when we want the timer to fire off. Here we are saying: "in one second".
3. Tell ASIO what to do when the wait (asychronously) expires. Notice that here we are using boost::bind() to let the compiler knows how to use the passed function in this context. I could translate it like this: "Let async_wait() uses doJob(), passing to it as first parameter what async_wait() already knows it should pass (i.e.: the error code) and as second parameter the c-string I provide here".

Canceling the request

If after we have created and set our deadline_timer, and before run() is called on the I/O Service object, we find out that there is no use anymore for this timer, we can simply cancel its execution:
boost::asio::deadline_timer dt2 = boost::asio::deadline_timer(ios);
dt2.expires_from_now(boost::posix_time::seconds(2));
dt2.async_wait(boost::bind(&doJob, _1, "Don't say hello"));
dt2.cancel();

The result of this code is that the doJob() function is called immediately, with the error code set to boost::asio::error::operation_aborted.

Implicit canceling /1

When a deadline_timer object is destroyed, it implicitly cancels itself, calling the set action with the operation_aborted error code. So, this code does not behave like someone could expect:
{
boost::asio::deadline_timer dt3 = boost::asio::deadline_timer(ios);

dt3.expires_from_now(boost::posix_time::seconds(3));
dt3.async_wait(boost::bind(&doJob, _1, "This hello is out of scope"));
}

When this deadline_timer object goes out of scope, it is destroyed, and an implicit call to cancel() is performed. As a result we will get immediately a "Never mind" message from doJob(), and not the three seconds delayed hello message.

Implicit canceling /2

We could get the same result as the previous example using a variable on the heap:
boost::asio::deadline_timer* dt4a = new boost::asio::deadline_timer(ios);

dt4a->expires_from_now(boost::posix_time::seconds(4));
dt4a->async_wait(boost::bind(&doJob, _1, "Doomed hello form heap"));
delete dt4a;

Since delete on the Deadline Timer is called before run() is called on the I/O Service object, we will never see the hello message, the doJob() function would be called instead with the error code set to operation_aborted.

Hello on the heap - without canceling

So, if we want the doJob() function to be called normally (no error set and after the timer expires), we have to call delete for the Deadline Timer after the run() method is executed on the I/O Service object:
boost::asio::deadline_timer* dt4b = new boost::asio::deadline_timer(ios);

dt4b->expires_from_now(boost::posix_time::seconds(4));
dt4b->async_wait(boost::bind(&doJob, _1, "Correct hello form heap"));

// ...
ios.run();

// memory cleanup
delete dt4b;

The deleting of dt4b is quite a sensitive matter. It has to be done after the ios.run() call, but when ios is still alive.
Besides, we have all the normal worries associated to the usage of raw pointers in C/C++. So, it is not a good idea writing code like that, if you can avoid it. Better using a smart pointer, as we see next.

Smart hello on the heap - without canceling

Using the good old std::auto_ptr we could rewrite the previous code in this way:
std::auto_ptr dt5(new boost::asio::deadline_timer(ios));
dt5->expires_from_now(boost::posix_time::seconds(5));
dt5->async_wait(boost::bind(&doJob, _1, "Smart hello form heap"));

Better to stress that we still have to be careful considering the relation between the I/O Service and the Deadline Timer: the latter has to be destroyed after ios.run() is called, but before ios goes out of scope.

Go to the full post

ASIO asychronous echo server

This post is ancient (Summer 2011), and I think that the code is just not working with a recent ASIO version. I wrote a new version of it on March 218 for the currently latest version of the library. Please, follow this link if you are interested in the matter, thanks!

The recently seen ASIO TCP/IP echo server is so simple that it does not actually ask for an asynchronous implementation (if it does not look simple enough to you, please have a look at an even simpler implementation). On the other hand, it is simple enough to to be modified for using an asynchronous approach with some hope of not getting lost in details.

Our echo server was basically built on two function, server() and session(). The idea was that any time a client was asking for a connection, a new session was generated in a new thread. So, the key line in that application was:
boost::thread t(session, sock);
You can find it at the bottom of the while loop in the server() function. It could be read as: run in a new thread the session function for the current socket (passed as a shareable smart pointer).

In such a simple context it looks good. Problem is that usually things tend to get more complicated, and managing multithreading explicitly could be a source of additional headaches. A way to avoid that could be relying on ASIO, using its asynchronous calls. Alas, this does not come for free, and we have to pay it with a more complex code structure. In this case this could look like a bit of overkilling, but sure make sense in real cases.

First step: our main function won't call anymore the original server() function but a new shiny asyncServer(), that would be something like that:
void asyncServer()
{
  try
  {
    boost::asio::io_service ios;
    AServer as(ios); // 1
    ios.run(); // 2
  }
  catch(std::exception& e)
  {
    std::cout << "Exception: " << e.what() << std::endl;
  }
}
1. A single server function is not enough anymore, we are about to design a class for modeling the asynchronous server, and here we'll instantiate an object of that class.
2. We'll let ASIO do the dirty job of managing our code, creating threads if and when required. Its run() function will take care of that, returning when nothing more is left to do.

Notice that we are not about to solve an annoying feature of our server: it still runs forever, and to kill it we have to issue an interrupt.

Let's see the AServer declaration:
#pragma once // 1
#include <boost/asio.hpp>
class ASession; // 2

using boost::asio::ip::tcp; // 3

class AServer
{
public:
  AServer(boost::asio::io_service& ios);
  void handleAccept(ASession* session, const boost::system::error_code& error);
private:
  void createSession();

  boost::asio::io_service& ios_;
  tcp::acceptor acp_;
};
1. I'm developing for VC++, so I'm using the infamous, but so handy, pragma once. If your compiler does not support this feature, you should use the clumsier, but more standard, include guards.
2. Forward declaration for the class that we'll use to model the behavior of our asynchronous session.
3. I'm not exactly a fan of using directive, but this nested namespace is way too boring.

If you played around a bit with the server echo example, you shouldn't be surprised by what you see in this class: an ASIO io_service, an acceptor to accept connections from clients, a way to create a new session ... the only perplexing piece of code should be that handleAccept() function. Actually, it looks pretty innocent:
void AServer::handleAccept(ASession* session, const boost::system::error_code& error)
{
  if(!error) // 1
  {
    session->start();
    createSession();
  }
  else // 2
    delete session;
}
1. If it is called in a "good" way, the passed session object is started (be patient for details on that), and a new session is created.
2. Otherwise, the passed session is "bad", so we just delete it.

So, handleAccept() is not a big issue. A bit more thinking is required by its caller:
void AServer::createSession()
{
  ASession* session = new ASession(ios_); // 1

  // using boost::asio::placeholders::error instead of _1 would be clearer, possibly
  acp_.async_accept( // 2
  session->socket(), // 3
  boost::bind(&AServer::handleAccept, this, session, _1)); // 4
  std::cout << "A new session is available to clients" << std::endl;
}
1. A new (asynchronous) session object is created.
2. We call the asynchronous accept method on the acceptor. Asynchronous meaning that returns immediately, not blocking the execution stream till its job is completed.
3. Its first parameter is the socket for the current session.
4. When async_accept() completes its job, meaning it has accepted a connection from a client socket, it would call handleAccept() for this object (this), passing to it the current session object itself and a mysterious other parameter, that would be task of handleAccept() to provide. If we want to make the code a bit more readable, we could use boost::asio::placeholders::error instead of _1, stressing the fact that we expect the caller putting an error code there.

This createSession() is called by two functions in AServer, its constructor:
AServer::AServer(boost::asio::io_service& ios) :
  ios_(ios), acp_(ios, tcp::endpoint(tcp::v4(), ECHO_PORT))
{
  createSession();
}
And the handleAccept() itself, that we have already seen above.

So, what happens when the free function asyncServer() creates an AServer object is that the AServer ctor calls createSession(), that creates a new object on the heap, and then asks the member acceptor to asynchronously accept a client connection in the session socket, and finally, when the accept call is completed, a call to handleAccept() will be performed, causing the current session to start and creating a new session, that would be available for a new connection with a client.

Basically the same behavior for the original echo server, if you don't let the asynchronicity confuse you.

Now the asynchronous session. Here is its class declaration:
#pragma once
#include <boost/asio.hpp>
#include "echo.h"

using boost::asio::ip::tcp;

class ASession
{
public:
  ASession(boost::asio::io_service& ios) : socket_(ios), connected_(false) {}
  ~ASession() { std::cout << "Session dtor" << std::endl; }

  tcp::socket& socket() { return socket_; }

  void start();
  void handleRead(const boost::system::error_code& error, size_t length);
  void handleWrite(const boost::system::error_code& error);
private:
  tcp::socket socket_;
  boost::array<char, MSG_LEN> data_;
  bool connected_;
};
Having seen the server class, I guess the reader won't be much surprised by this design. In the private section of the class we have a socket, a data buffer for communication, and a flag to keep track of the session status. Among the public methods we have a couple of handleXXX() that we should suspect linked to the asynchronous design of this class.

We remember that ASession::start() is called by AServer::handleAccept() when the asynchronous call to accept on the socket owned by the ASession object itself is accomplished:
void ASession::start()
{
  std::cout << "Starting session" << std::endl;
  connected_ = true; // 1
  socket_.async_read_some(boost::asio::buffer(data_), // 2
  boost::bind(&ASession::handleRead, this, _1, _2)); // 3
}
1. Keep track of the fact that the connection is started.
2. Start reading asynchronously on the socket (connected to a client), using as buffer the private data member.
3. When async_read_some() is done with its job, it is going to call ASession::handleRead() for the current object, passing a couple of parameters. If we want to make the code more clear, we could use the ASIO placehoder boost::asio::placeholders::error instead of _1, and boost::asio::placeholders::bytes_transferred for _2.

In any case the sense of this function is that the read of data coming from the client is done asynchronously, and at the end of it the control is passed to handleRead(). So, let's see this other function:
void ASession::handleRead(const boost::system::error_code& error, size_t bytes)
{
  if(data_[bytes-1] == '\0') // 1
  {
    std::cout << "Client sent a terminator" << std::endl;
    --bytes;
    connected_ = false; // 2
  }

  if(!error && bytes) // 3
  {
    std::cout << "Writing back " << bytes << " characters to the client" << std::endl;
    boost::asio::async_write(socket_, boost::asio::buffer(data_, bytes),
    boost::bind(&ASession::handleWrite, this, _1)); // 4
  }
  else
    delete this; // 5
}
1. This should be a sort of deja vu, being so close to the code of our old echo server. We check if the last character in the buffer is a NUL, being this by our convention the terminator for the connection between client and server.
2. Here we are using a member variable, connect_, to keep track of the termination, since we set it here but we are going to check it in handleWrite().
3. If the asynchronous read succeeded and the buffer is not empty, we send back the data to the client, using async_write().
4. When done, async_write() will call handleWrite() on the current object. If you feel _1 is not descriptive enough, you could use instead boost::asio::placeholders::error.
5. This is interesting. When the session sees it is not useful anymore, it commits suicide, calling delete on itself.

Finally, here is handleWrite(). We have seen it is called by the asynchronous write call in handleRead():
void ASession::handleWrite(const boost::system::error_code& error)
{
  if(!error && connected_) // 1
  {
    std::cout << "Ready for a new read" << std::endl;
    socket_.async_read_some(boost::asio::buffer(data_),
    boost::bind(&ASession::handleRead, this, _1, _2)); // 2
  }
  else
    delete this; // 3
}
1. Only if there was no error in the asynchronous write, and if no terminator was detected in the data sent by the client, we make another asynchronous read call on the socket.
2. As you probably suspected, the placeholders could be replaced by boost::asio::placeholders::error and boost::asio::placeholders::bytes_transferred.
3. Here again, if the session object detect is out of scope, delete itself.

This post is based on the official documentation Boost ASIO Echo examples.

Go to the full post

ASIO TCP echo client

Here we are about to write a client for the ASIO TCP echo server described previously.

Its task is giving a way its user to input a line of text that would be sent to the server. Since the server is keeping the connection alive until receives a NUL character, the client should send it after the string, as input by the user, to close the communication.

Once the sending is performed, the client uses the same socket to get the answer from the server.

This post is ancient, June 2011, C++ and ASIO are changed a bit in the meantime, so, on March 2018, I have reviewed post and code. Please follow the link to the newer version.

Here is the client code. Notice it uses an include file, echo.h, that has been already shown, being used by the server (and the main - not shown, since it is embarassingly simple):
#include <iostream>
#include <boost\asio.hpp>
#include "echo.h"

void client()
{
try
{
boost::asio::io_service ios;

boost::asio::ip::tcp::resolver resolver(ios); // 1.
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), ECHO_HOST, ECHO_PORT_S);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

boost::asio::ip::tcp::socket sock(ios); // 2.
sock.connect(*iterator);

std::cout << "Enter message: "; // 3.
std::string request;
getline(std::cin, request);
boost::asio::write(sock, boost::asio::buffer(request));

char data[1] = {'\0'};
boost::asio::write(sock, boost::asio::buffer(data, 1)); // 4.

while(true) // 5.
{
boost::array<char, MSG_LEN> reply;

boost::system::error_code error;
size_t length = sock.read_some(boost::asio::buffer(reply), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.

std::cout.write(reply.c_array(), length);
}
std::cout << std::endl; // 6.
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << std::endl;
}
}

1. We use a resolver to find the server socket on the expected host and port.
2. We create a client socket, and connect it to the server one.
3. The client user is asked to input a std::string, we use std::getline() to read it, then we convert it in a ASIO buffer, and write it in the socket.
4. We signal the server we are done, sending a terminator.
5. Now we use the socket to read the feedback from the server. We loop until the communication is closed, reading a chunk of data and outputting that to the standard console.
6. Once the reply is fully received, we add a new line to it.

It could be interesting comparing this client with the one written for the first TCP ASIO client written for a minimal client/server connection. In that case the client did not send any data to the server, it was just a receiver.

But it could be worthy noticing the different approach to the socket connection to the server. Here we check just the first result returned by the resolver, if it is not a "good" connection, an exception is thrown, and the application terminates. The other client is on this aspect more careful. It loops on all the results returned by the resolver looking for the first "good" one.

This post is based on the official documentation Boost ASIO Echo examples.

Go to the full post

ASIO TCP echo server

My first ASIO TCP server application was flawed in many ways, and its most substantial flaw was that it managed just one connection, shutting down after aknowledging it.

Here we rewrite it, solving this limit. The idea is that it sits waiting for a connection, once it receive a request from a client a new thread is started to manage that session, and a new socket is created to wait for a new connection.

This post is ancient, June 2011, C++, ASIO (and myself) have changed a bit in the meantime, so, on March 2018, I have reviewed post and code. Please follow the link to the newer version.

But before caring of the code, a short list of project properties that have to be set (if you are working with Visual C++ 2010) for using the Boost-ASIO library.

A fast way to access the project properties is right clicking on the project name in the Solution Explorer window and then choose the last item in the menu (Properties).

Then set these three values:

C/C++, General
- Additional Include Directories: your local Boost root folder
- Preprocessor Definition: _WIN32_WINNT=0x0501
Linker, General
- Additional Library Directories: your local Boost lib folder

Once done that I wrote a main function that could call a couple of function, server() or client(), accordingly to the argument passed from the shell to the application. It would be better to let the user decide for port number (and the server IP address, for the client run) but I made it simpler assuming both client and server run on localhost and using a (carefully chosen) fixed port number.

All functions (main, client, and server) would use these basic information stored in a common include file, echo.h:
#pragma once // 1.

static const int ECHO_PORT = 50013;
static const char* ECHO_PORT_S = "50013";
static const char* ECHO_HOST = "localhost";

const int MSG_LEN = 8; // 2.

extern void server();
extern void client();

1. The pragma once makes this code stricty bounded to the MS compiler, feel free to use the more standard include guard mechanism instead.
2. This constant should be set to a more sensible value, like 80, representing the normally expected length of a message exchanged between client and server. Here is kept so low for testing purposes.

The server.cpp file keeps all the server related code in it. It starts with a bunch of includes and a typedef:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/smart_ptr.hpp>

#include "echo.h"

typedef boost::shared_ptr<boost::asio::ip::tcp::socket> SmartSocket;

The typedef is aimed to reduce typing and making code a bit clearer. SmartSocket is a smart pointer (a sharable one) based on the Boost ASIO TCP/IP socket class. It is used as parameter passed to a local function that we are going to see in details in a while, for the moment we just have a glimpse at its declaration:
namespace // 1.
{
void session(SmartSocket sock) // 2.
{
// ...
}
}

1. The function is in an anonymous namespace, that means it is visible only locallly.
2. It accepts in input a parameter, sock, that is a smart pointer to a socket.

But let see now the definition of the server() function:
void server()
{
boost::asio::io_service ios; // 1.

boost::asio::ip::tcp::acceptor acp(ios,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), ECHO_PORT)); // 2.

while(true) // 3.
{
SmartSocket sock(new boost::asio::ip::tcp::socket(ios)); // 4.
std::cout << "Waiting for a new connection" << std::endl;
acp.accept(*sock); // 5.
std::cout << "Connection accepted" << std::endl;
boost::thread t(session, sock); // 6.
}
}

1. This is the ASIO io_service object we are going to use to create all the relevant ASIO object in this example.
2. To accept a socket connection we need an acceptor, created using the local io_service instance and an endpoint specifying the protocol and the used port.
3. We are looping forever - this is not actually beautiful, but we are going to live with it, for the moment. When we are done with the server we kill it sending it an interrupt.
4. A smart pointer to a TCP/IP socket is created.
5. The application sits on the acceptor waiting for a client that would be connected to the socket we just created.
6. Here is the magic. We create a new thread on the session() function passing to it the smart pointer to the socket and then we start a new iteration of the while loop, creating a new socket smart pointer instance.

So, any time a client connect to the server, a new socket is created an make available for a new connection.

As promised, let's see now what happens in the session() function. Its basic idea is that it gets characters from the client, in bunches of MSG_LEN or less, and it sends them back to the client. As usual, we have to decide how the client would say to the server that it is done, and it does not want to send it anything anymore. I decided to use the NUL character, '\0', as terminator. When it is seen at the end of a chunk of data, the server knows the client considers terminated the communication:
void session(SmartSocket sock)
{
try
{
bool pending = true;
while(pending)
{
boost::array<char, MSG_LEN> data;

boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.

if(data[length-1] == '\0') // 1.
{
std::cout << "Client sent a terminator" << std::endl;
--length;
pending = false;
}

if(length) // 2.
{
std::cout << "echoing " << length << " characters" << std::endl;
boost::asio::write(*sock, boost::asio::buffer(data, length));
}
}
}
catch (std::exception& e)
{
std::cerr << "Exception in thread: " << e.what() << std::endl;
}
}

1. We check if the last character in the current chunk of data is a NUL, if this the case the loop should be interrupted.
2. If there is something (besides the terminator) in the buffer read from the client, we send it back to it.

This post is based on the official documentation Boost ASIO Echo examples, here is the link to the original code for the TCP/IP blocking Echo server example.

Go to the full post