Boost ASIO library is the defacto standard for network and low-level I/O programming. It has a great documentation available online, but there are a lot of methods and classes in the library. Therefore, if it is your first attempt to use it, it can be a bit challenging.
Since there is a lot of ground to cover in the Boost ASIO library, I will only cover the work scheduler and the synchronous methods in this post. The asynchronous methods and timers will be covered in following posts.
During this post I use CMake to configure and build the project and as dependency manager I will use conan.
As always, all the code used in this post is available in this repo.
The videos are made with asciinema, that means you can copy from the video.
The IO Service is the mainstay of the Boost ASIO. Basically, it is in charge of scheduling the work to be done. In this section, I will use the IO Service to demonstrate how it performs the scheduling. However, it is not recommended to use it for this purpose, as Sean Parent shows in this talk.
The whole idea of this section is to help you understand how the Boost ASIO works underneath.
The code for this simple example is to just show how the IO Service can perform some work. The code is quite straightforward, it provides 6 tasks to the IO Service and then it executes them.
The output of the previous code is what everybody can expect.
The code for the two workers is a bit more complicated. The idea is the same, but with two threads executing tasks instead of one. The complexity of the previous code is the usage of threads, but it is not overwhelming.
The output of the two workers code can be the same as from the one worker section. However, it is not guaranteed that it would be the same. This can be seen in the following execution:
In order to use Boost ASIO for network it is not required to know how the IO Service works. Actually, the explicit usage of IO Service as it is done in the previous section is not recommended.
In this section, the usage of synchronous calls is shown in order to create a client and a server programs.
The code for the client sends a message - provided as a parameter - to the server. After that the client reads the answer from the server and prints it in the standard output.
The first interesting part of the code is the resolution of the hostname and the port. Pay attention to the fact that the “port” is a string. It is because it can be a number or a service name (i.e. “https” as port would connect to port 443).
The next interesting part of the code is the send of the message to the end point. The interesting bit is how the data is send. In this case, the message is stored in a std::string, but it is required to be transformed into a boost::asio::buffer.
The last interesting part of the code is the read a message from the end point. In this case, a boost::asio::streambuf is used to retrieve the data from the server. However, it could have been done in other ways as it is shown in the server case. The errors are another interesting part of the code. The “success” error (when the first part of the conditional is false) will happen when the buffer is full. However, the boost::asio::error::eof will occur when the end point closes the connection.
The code for the server receives a message, then it returns the message backwards to the sender.
The first interesting part of the code is the socket and acceptor. In this case the port is a number. Another good part is how the usage of IPv4 only has been specified.
The last interesting part of the code is the read a message. In this case, it is using a plain char array to read parts of the message and store it in a std::ostringstream. Pay attention to how it keeps track of the amount of data that has been read and stores that much information only.
The simplicity of the Boost ASIO is matched only by its power. It is quite simple to create a synchronous client/server application. These are the basics of Boost ASIO and it should allow you to understand more complex usage of it.