In &io_service::run
, io_service
is not a type but the local variable by that name.
Starting from https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp
io_context.run();
Needs to be like
std::thread t([&] { io_context.run(); });
// ...
t.join();
Or if you insist:
std::thread t(boost::bind(&boost::asio::io_context::run, &io_context));
I would use a thread_pool to shortcut all the complexities¹:
boost::asio::thread_pool io(1);
server s(io.get_executor(), std::atoi(argv[1]));
// ...
io.join();
A trivial edit to the class interface is required (see e.g. Boost 1.70 io_service deprecation)
Live On Coliru
//
// async_tcp_echo_server.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2020 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 http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
using boost::asio::ip::tcp;
class session : public std::enable_shared_from_this<session> {
public:
session(tcp::socket socket) : socket_(std::move(socket)) {}
void start() { do_read(); }
private:
void do_read() {
auto self(shared_from_this());
socket_.async_read_some(
boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length) {
if (!ec) {
do_write(length);
}
});
}
void do_write(std::size_t length) {
auto self(shared_from_this());
boost::asio::async_write(
socket_, boost::asio::buffer(data_, length),
[this, self](boost::system::error_code ec, std::size_t /*length*/) {
if (!ec) {
do_read();
}
});
}
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server {
public:
template <typename Executor>
server(Executor ex, short port)
: acceptor_(ex, tcp::endpoint(tcp::v4(), port)) {
do_accept();
}
private:
void do_accept() {
acceptor_.async_accept(
[this](boost::system::error_code ec, tcp::socket socket) {
if (!ec) {
std::make_shared<session>(std::move(socket))->start();
}
do_accept();
});
}
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[]) {
try {
if (argc != 2) {
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
boost::asio::thread_pool io(1);
server s(io.get_executor(), std::atoi(argv[1]));
// ...
io.join();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}
¹ see e.g. Should the exception thrown by boost::asio::io_service::run() be caught?