The simplest server there is

168

According to Wikipedia,

A server is a computer program or a device that provides functionality for other programs or devices, called “clients”.

This is a very good description as well as the fact that server is nothing more than this. There is nothing really magic about servers, it's just an application that receives some data from other applications and provides some data back.

We will start from the simplest server that comes to mind — UDP echo server. It does the following:

Receive any data that was sent to UDP port 15001

Send received data back to the sender “as is”.

You can actually choose almost any port for your server. There are many commonly-used ports for different services which you can find here: List of TCP and UDP port numbers However, usually only few of these services are used at the same time on a freshly installed OS.

Now take a look at this source code:

#include <boost/asio.hpp>

int main()
{
    std::uint16_t port = 15001;

    boost::asio::io_context io_context;
    boost::asio::ip::udp::endpoint receiver(boost::asio::ip::udp::v4(), port);
    boost::asio::ip::udp::socket socket(io_context, receiver);

    for(;;)
    {
        char buffer[65536];
        boost::asio::ip::udp::endpoint sender;
        std::size_t bytes_transferred = socket.receive_from(boost::asio::buffer(buffer), sender);
        socket.send_to(boost::asio::buffer(buffer, bytes_transferred), sender);
    }

    return 0;
}

You won't find downloadable .cpp files for this lesson because the code above is a complete UDP echo server! I've omitted logging and error handling to keep things as simple as possible. We will talk about error handling a bit later. So, what's going on there?

boost::asio::io_context (former boost::asio::io_service) is a sort of main I/O service provider. At this point you can consider it as an executor of scheduled tasks. You'll understand its purpose right after we jump into asynchronous control flow which will happen very soon.

boost::asio::ip::udp::endpoint is a pair of an IP address and a port.

boost::asio::ip::udp::socket is... a socket. You can consider socket as a file handle designed for the network communication. When you open a file you usually get a file handle. When you do network communication you use a socket.

Each socket is attached to some io_context and should be constructed from io_context refecence. The second parameter is endpoint — an IP address and a port that used to receive incoming datagrams (in case of UDP) or connections (in case of TCP).

boost::asio::ip::udp::v4() returns an object which you should consider at this point as just default UDP network interface.

boost::asio::buffer() is a view of a buffer. It holds a pointer and a buffer's size and doesn't own the memory allocated. In our case it points to our char array.

socket::receive_from waits for the incoming UDP packet, fills buffer with received data, and fills sender with an information about the sender which is also a pair of an IP address and a port.

socket::send_to sends UDP packet using a data from the buffer view. Recipient of the packet is passed as a second argument which in our case is the sender itself since it is an echo server.

So, we did the following: we created UDP socket and configured it to wait for UDP messages on 15001 UDP port. After that we started an infinite loop where we wait for incoming UDP messages and send them back to the sender right away.

Congratulations! You've just created your first server with C++ and Boost.Asio!

Lesson 2
Share this page:

Learning plan

What should you know before get started
A brief description of the difference between network transport protocols
3. The simplest server there is
What is server anyway? The most simple example
It's time to say “goodbye” to a synchronous I/O
The first simple asynchronous TCP server
How to handle Boost.Asio errors