C-Programmierung

Boost Asio

boost::basics | | Beispiel zu Boost

boost.asio = [a]synchronous IO with C++

Here is the core snippet from a slightly modified synchronous boost example (for the original example see the boost tutorial). The example makes a synchronous query to a daytime server via tcp:

The data transfer between the endpoints of an TCP/IP connections is managed asynchronously by an io service. We have to create an instance of that service:

boost::asio::io_service io_service;

A boost.asio tcp resolver takes a tcp::resolver::query object and turns it into a list of tcp endpoints. We construct a tcp query using the name of the server, usually the server’s ip address, and the name of the service, in this case “daytime”. Note: The daytime service is usually associated with TCP port 13.

tcp::resolver::query query(server, "daytime");

The list of tcp endpoints is returned using an iterator of type ip::tcp::resolver::iterator.

tcp::resolver resolver(io_service);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

Now we create and connect a so called socket. A socket is a connection between the two endpoints, through which data can be transferred bidirectionally over a specific port of the endpoints.

tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);

The list of endpoints obtained above may contain both IPv4 and IPv6 endpoints, so we need to try each of them until we find one that works. This keeps the client program independent of a specific IP version. The boost::asio::connect() function does this for us automatically.

The connection is now open. All we need to do now is read the response from the daytime service through the socket.

We use a boost::array to hold the received data. The boost::asio::buffer() function automatically determines the size of the array to help prevent buffer overruns. Instead of a boost::array, we could have used a char [] or std::vector.

for (;;)
{
   boost::array<char, 128> buf;
   boost::system::error_code error;

   size_t len = socket.read_some(boost::asio::buffer(buf), error);

When the server closes the connection, the ip::tcp::socket::read_some() function will exit with the boost::asio::error::eof error, which is how we know to exit the loop.

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(buf.data(), len);
}

Supposed the above client source is available in client.cpp, we compile the client via:

Linux:

g++ -I path/to/boost client.cpp -L path/to/boost/stage/lib -lboost_system -lboost_thread -lpthread -lrt -o client

MacOS X:

g++ -I path/to/boost client.cpp -L path/to/boost/stage/lib -lboost_system -lboost_thread -o client

That’s the client side. The server side is illustrated in another boost tutorial.

A running daytime server, as described in the tutorial, is available at schorsch.efi.fh-nuernberg.de, port 13. You can test your client with it.

boost::basics | | Beispiel zu Boost

Options: