Boost C++ Libraries Home Libraries People FAQ More

Home | Reference | Tutorial | Examples | Design

Daytime.6 - An asynchronous UDP daytime server

The main() function

int main()
{
  try
  {

Create a server object to accept incoming client requests, and run the boost::asio::io_service object.

    boost::asio::io_service io_service;
    udp_server server(io_service);
    io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

The udp_server class

class udp_server
{
public:

The constructor initialises a socket to listen on UDP port 13.

  udp_server(boost::asio::io_service& io_service)
    : socket_(io_service, udp::endpoint(udp::v4(), 13))
  {
    start_receive();
  }

private:
  void start_receive()
  {

The function boost::asio::ip::udp::socket::async_receive_from() will cause the application to listen in the background for a new request. When such a request is received, the boost::asio::io_service object will invoke the handle_receive() function with two arguments: boost::asio::error, and bytes_transferred.

    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

The function handle_receive() will service the client request.

  void handle_receive(const boost::asio::error& error,
      std::size_t /*bytes_transferred*/)
  {

The error parameter contains the result of the asynchronous operation. Since we only provide the 1-byte recv_buffer_ to contain the client's request, the boost::asio::io_service object would return an error if the client sent anything larger. We can ignore such an error if it comes up.

    if (!error || error == boost::asio::error::message_size)
    {

Determine what we are going to send.

      boost::shared_ptr<std::string> message(
          new std::string(make_daytime_string()));

We now call boost::asio::ip::udp::socket::async_send_to() to serve the data to the client.

      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
          boost::bind(&udp_server::handle_send, this, message,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

When initiating the asynchronous operation, and if using boost::bind, you must specify only the arguments that match the handler's parameter list. In this program, both of the argument placeholders (boost::asio::placeholders::error and boost::asio::placeholders::bytes_transferred) could potentially have been removed.

Start listening for the next client request.

      start_receive();

Any further actions for this client request are now the responsibility of handle_send().

    }
  }

The function handle_send() is invoked after the service request has been completed.

  void handle_send(boost::shared_ptr<std::string> /*message*/,
      const boost::asio::error& /*error*/, std::size_t /*bytes_transferred*/)
  {
  }

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array<char, 1> recv_buffer_;
};

See the full source listing
Return to the tutorial index
Previous: Daytime.5 - A synchronous UDP daytime server
Next: Daytime.7 - A combined TCP/UDP asynchronous server
Copyright © 2003 - 2006 Christopher M. Kohlhoff


Home | Reference | Tutorial | Examples | Design