TCP Echo Server — lambdas
// TCP echo server implemented with Boost.ASIO and C++11 lambdas
//
// Copyright (c) 2021 Andrzej Krzemieński (akrzemi1 at gmail dot com)
//
// Based heavily on the example by Christopher M. Kohlhoff at:
// https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
namespace asio = boost::asio;
namespace sys = boost::system;
using boost::asio::ip::tcp;
void report_error(std::string_view component, sys::error_code ec)
{
std::cerr << component << " failure: "
<< ec << " ()" << ec.message() << ")\n";
}
void session(tcp::socket socket)
{
struct session_state
{
tcp::socket _socket;
char _data[1024];
explicit session_state(tcp::socket s) : _socket(std::move(s)) {}
static void do_read(std::shared_ptr<session_state> state)
{
state->_socket.async_read_some(asio::buffer(state->_data),
[state](sys::error_code ec, std::size_t length)
{
if (!ec)
do_write(state, length);
else if (ec == asio::error::eof)
std::cerr << "Session done \n";
else
report_error("Session", ec);
});
}
static void do_write(std::shared_ptr<session_state> state, std::size_t length)
{
asio::async_write(state->_socket, asio::buffer(state->_data, length),
[state](sys::error_code ec, std::size_t /*length*/)
{
if (!ec)
do_read(state);
else
report_error("Session", ec);
});
}
};
auto s = std::make_shared<session_state>(std::move(socket));
session_state::do_read(s);
}
class listener
{
tcp::acceptor _acceptor;
public:
listener(asio::io_context& context, unsigned short port)
: _acceptor{context, {tcp::v4(), port}}
{}
void operator() ()
{
async_accept_one();
}
private:
void async_accept_one()
{
_acceptor.async_accept(
[this](sys::error_code ec, tcp::socket socket)
{
if (!ec)
session(std::move(socket));
else
report_error("Listener", ec);
async_accept_one();
});
}
};
int main()
{
try
{
asio::io_context context;
asio::signal_set signals(context, SIGINT, SIGTERM);
signals.async_wait([&](auto, auto){ context.stop(); });
auto listen = listener(context, 55555);
listen();
context.run();
std::cerr << "Server done \n";
}
catch (std::exception& e)
{
std::cerr << "Server failure: " << e.what() << "\n";
}
}
Like this:
Like Loading...