Basic asio example

I had a lot of trouble find a really basic example (hey the stuff I want to do is not that hard) for using the boost::asio library. This library is supposed to be the bee’s knees and will be included in C++ TR2 (and is already included in Boost) so I thought it was worthwhile to fight with it for some time…

Here’s a sample app adapted from the included blocking_tcp_echo_server.cpp

//
// blocking_tcp_echo_server.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at [url=http://www.boost.org/LICENSE_1_0.txt]http://www.boost.org/LICENSE_1_0.txt[/url])
//

#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>
#include "asio.hpp"

using asio::ip::tcp;

const int max_read_length = 10;
const int max_response_length = 100;

typedef boost::shared_ptr<tcp::socket> socket_ptr;

void session(socket_ptr sock)
{
        try
        {
                for (;;)
                {
                        // Reading demonstration
                        char data[max_read_length];
                        asio::error_code error;
                        size_t length = sock->read_some(asio::buffer(data, max_read_length), error);
                        if (error == asio::error::eof)
                        {
                                std::cout << "Socket closed by peer" << std::endl;
                                break; // Connection closed cleanly by peer.
                        }
                        else if (error)
                        {
                                throw asio::system_error(error); // Some other error.
                        }
                        std::cout << "Read " << length << " bytes" << std::endl;

                        // Writing demonstration
                        char response[max_response_length];
                        sprintf((char*)response, "Read %d bytes dude it rocks\n", length);
                        length = asio::write(*sock, asio::buffer(response, strlen(response)), asio::transfer_all(), error);
                        std::cout << "Written " << length << " bytes " << std::endl;
                        if (error)
                        {
                                std::cout << "Error during writing: " << error.message() << std::endl;
                                return;
                        }

                        // uncomment this if you just want to echo
                        //asio::write(*sock, asio::buffer(data, length));
                }
        }
        catch (std::exception& e)
        {
                std::cerr << "Exception in thread: " << e.what() << "\n";
        }
}

void server(asio::io_service& io_service, short port)
{
        tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
        for (;;)
        {
                socket_ptr sock(new tcp::socket(io_service));
                std::cout << "Blocking in accept" << std::endl;
                a.accept(*sock);
                std::cout << "Got a connection" << std::endl;

                // uncomment this to multithread
                // asio::thread t(boost::bind(session, sock));

                // only need one simultaneous thread
                session(sock);
        }
}

int main(int argc, char* argv[])
{
        try
        {
                if (argc != 2)
                {
                        std::cerr << "Usage: blocking_tcp_echo_server <port>\n";
                        return 1;
                }

                asio::io_service io_service;



                using namespace std; // For atoi.
                server(io_service, atoi(argv[1]));
        }
        catch (std::exception& e)
        {
                std::cerr << "Exception: " << e.what() << "\n";
        }

        return 0;
}