| Home | Libraries | People | FAQ | More

# 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