Book Image

Boost.Asio C++ Network Programming Cookbook

By : Dmytro Radchuk
Book Image

Boost.Asio C++ Network Programming Cookbook

By: Dmytro Radchuk

Overview of this book

Starting with recipes demonstrating the execution of basic Boost.Asio operations, the book goes on to provide ready-to-use implementations of client and server applications from simple synchronous ones to powerful multithreaded scalable solutions. Finally, you are presented with advanced topics such as implementing a chat application, implementing an HTTP client, and adding SSL support. All the samples presented in the book are ready to be used in real projects just out of the box. As well as excellent practical examples, the book also includes extended supportive theoretical material on distributed application design and construction.
Table of Contents (13 chapters)
Boost.Asio C++ Network Programming Cookbook
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
Index

Binding a socket to an endpoint


Before an active socket can communicate with a remote application or a passive socket can accept incoming connection requests, they must be associated with a particular local IP address (or multiple addresses) and a protocol port number, that is, an endpoint. The process of associating a socket with a particular endpoint is called binding. When a socket is bound to an endpoint, all network packets coming into the host from the network with that endpoint as their target address will be redirected to that particular socket by the operating system. Likewise, all the data coming out from a socket bound to a particular endpoint will be output from the host to the network through a network interface associated with the corresponding IP address specified in that endpoint.

Some operations bind unbound sockets implicitly. For example, an operation that connects an unbound active socket to a remote application, binds it implicitly to an IP address and a protocol port number chosen by the underlying operating system. Usually, the client application doesn't need to explicitly bind an active socket to a specific endpoint just because it doesn't need that specific endpoint to communicate with the server; it only needs any endpoint for that purpose. Therefore, it usually delegates the right to choose the IP address and the port number to which the socket should be bound to the operating system. However, in some special cases, the client application might need to use a specific IP address and a protocol port number to communicate with the remote application and therefore will bind its socket explicitly to that specific endpoint. We wouldn't consider these cases in our book.

When socket binding is delegated to the operating system, there is no guarantee that it will be bound to the same endpoint each time. Even if there is a single network interface and a single IP address on the host, the socket may be bound to a different protocol port number every time the implicit binding is performed.

Unlike client applications that usually don't care through which IP address and protocol port number its active socket will be communicating with the remote application, the server application usually needs to bind its acceptor socket to a particular endpoint explicitly. This is explained by the fact that the server's endpoint must be known to all the clients that want to communicate with it and should stay the same after the server application is restarted.

This recipe explains how to bind a socket to particular endpoint with Boost.Asio.

How to do it…

The following algorithm describes steps required to create an acceptor socket and to bind it to an endpoint designating all IP addresses available on the host and a particular protocol port number in the IPv4 TCP server application:

  1. Obtain the protocol port number on which the server should listen for incoming connection requests.

  2. Create an endpoint that represents all IP addresses available on the host and the protocol port number obtained in the step 1.

  3. Create and open an acceptor socket.

  4. Call the acceptor socket's bind() method, passing the endpoint object as an argument to it.

The following code sample demonstrates possible implementation of the algorithm. It is assumed that the protocol port number has already been obtained by the application:

#include <boost/asio.hpp>
#include <iostream>

using namespace boost;

int main()
{
  // Step 1. Here we assume that the server application has
  // already obtained the protocol port number.
  unsigned short port_num = 3333;

  // Step 2. Creating an endpoint.
  asio::ip::tcp::endpoint ep(asio::ip::address_v4::any(),
    port_num);

  // Used by 'acceptor' class constructor.
  asio::io_service ios;

  // Step 3. Creating and opening an acceptor socket.
  asio::ip::tcp::acceptor acceptor(ios, ep.protocol());

  boost::system::error_code ec;

  // Step 4. Binding the acceptor socket.
  acceptor.bind(ep, ec);

  // Handling errors if any.
  if (ec != 0) {
    // Failed to bind the acceptor socket. Breaking
    // execution.
    std::cout << "Failed to bind the acceptor socket."
      << "Error code = " << ec.value() << ". Message: "
      << ec.message();

    return ec.value();
  }

  return 0;
}

How it works…

We begin by obtaining a protocol port number in step 1. The process of obtaining this parameter is beyond the scope of this recipe; therefore, here we assume that the port number has already been obtained and is available at the beginning of the sample.

In step 2 we create an endpoint representing all IP addresses available on the host and the specified port number.

In step 3 we instantiate and open the acceptor socket. The endpoint we created in step 2 contains information about the transport protocol and the version of the underlying IP protocol (IPv4). Therefore, we don't need to create another object representing the protocol to pass it to the acceptor socket's constructor. Instead, we use the endpoint's protocol() method, which returns an object of the asio::ip::tcp class representing the corresponding protocols.

The binding is performed in step 4. This is quite a simple operation. We call the acceptor socket's bind() method, passing an object representing an endpoint to which the acceptor socket should be bound as an argument of the method. If the call succeeds, the acceptor socket is bound to the corresponding endpoint and is ready to start listening for incoming connection requests on that endpoint.

Tip

Downloading the example code

You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

There's more…

UDP servers don't establish connections and use active sockets to wait for incoming requests. The process of binding an active socket is very similar to binding an acceptor socket. Here, we present a sample code demonstrating how to bind a UDP active socket to an endpoint designating all IP addresses available on the host and a particular protocol port number. The code is provided without explanation:

#include <boost/asio.hpp>
#include <iostream>

using namespace boost;

int main()
{
  // Step 1. Here we assume that the server application has
  // already obtained the protocol port number.
  unsigned short port_num = 3333;

  // Step 2. Creating an endpoint.
  asio::ip::udp::endpoint ep(asio::ip::address_v4::any(),
    port_num);

  // Used by 'socket' class constructor.
  asio::io_service ios;

  // Step 3. Creating and opening a socket.
  asio::ip::udp::socket sock(ios, ep.protocol());

  boost::system::error_code ec;

  // Step 4. Binding the socket to an endpoint.
  sock.bind(ep, ec);

  // Handling errors if any.
  if (ec != 0) {
    // Failed to bind the socket. Breaking execution.
    std::cout << "Failed to bind the socket."
      << "Error code = " << ec.value() << ". Message: "
      << ec.message();

    return ec.value();
  }

  return 0;
}

See also

  • The Creating an endpoint recipe provides more information on endpoints

  • The Creating an active socket recipe provides more details about the asio::io_service and asio::ip::tcp classes and demonstrates how to create and open an active socket

  • The Creating a passive socket recipe provides information about passive sockets and demonstrates how to create and open them