Can't initialize boost::asio::io_service

51 Views Asked by At

I'm trying to write a server using boost/asio, I have "class Server", when I try to pass in the parameters of this class io_service, An error occurs that this io_service not available in boost/asio.

Server.h

#pragma once

#define _WIN32_WINNT

#include <iostream>
#include <string>
#include <boost/asio.hpp>

class Server
{
    std::string server_address;
    std::string server_port;
    boost::asio::io_service server_io_service;
    boost::asio::ip::tcp::endpoint server_ep;
    boost::asio::ip::tcp::acceptor server_acceptor;
    boost::asio::ip::tcp::socket server_socket;


public:
    explicit Server(std::string address, std::string port, boost::asio::io_service& io_service);
    explicit Server();
    ~Server();

    void start_listening() noexcept; 
};

Server.cpp

#include "../headers/server.h"

Server::Server(std::string address, std::string port, boost::asio::io_service& io_service) :
    server_address(address),
    server_port(port),
    server_io_service(io_service), // error
    server_ep(boost::asio::ip::tcp::v4(), std::stoi(port)),
    server_acceptor(io_service, server_ep),
    server_socket(io_service)
{}

output [1/2] Building CXX object CMakeFiles\Server.dir\source\Server.cpp.obj FAILED: CMakeFiles/Server.dir/source/Server.cpp.obj C:\PROGRA~1\MICROS~4\2022\COMMUN~1\VC\Tools\MSVC\1438~1.331\bin\Hostx64\x64\cl.exe /nologo /TP -ID:\boost_1_84_0\boost_1_84_0 /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Ob0 /Od /RTC1 -std:c++20 -ZI /showIncludes /FoCMakeFiles\Server.dir\source\Server.cpp.obj /FdCMakeFiles\Server.dir\ /FS -c D:\C++\Server\source\Server.cpp D:\boost_1_84_0\boost_1_84_0\boost\asio\detail\config.hpp(667): fatal error C1017: недопустимое константное выражение целого типа ninja: build stopped: subcommand failed.

(https://i.stack.imgur.com/rYYeN.png)

I tried to find information about this problem in the documentation "Boost/asio", but I couldn't find anything about it.

1

There are 1 best solutions below

0
sehe On

io_service is not copyable. It's also deprecated.

io_context replaces it. It is also not copyable.

So, either store a reference to it:

class Server {
    std::string       address_;
    std::string       port_;
    asio::io_context& ioc_;
    tcp::endpoint     ep_;
    tcp::acceptor     acceptor_{ioc_, {{}, static_cast<uint16_t>(std::stoi(port_))}};
    tcp::socket       socket_{ioc_};

  public:
    explicit Server(std::string address, std::string port, asio::io_context& ioc)
        : address_(std::move(address))
        , port_(std::move(port))
        , ioc_(ioc) {}

    void start_listening() noexcept;
};

Or (better yet) store an executor to it

class Server {
    std::string   address_;
    std::string   port_;
    tcp::endpoint ep_;
    tcp::acceptor acceptor_;

  public:
    explicit Server(asio::any_io_executor ex, std::string address, std::string port)
        : address_(std::move(address))
        , port_(std::move(port))
        , acceptor_(ex, {{}, static_cast<uint16_t>(std::stoi(port_))}) {}

    void start_listening() noexcept;
};

Now it's weird to accept the server_address which is unused. Just accept uint16_t port instead, or the full endpoint.

Full Demo

Live On Coliru

#include <iostream>
#include <string>
#include <boost/asio.hpp>
namespace asio = boost::asio;
using asio::ip::tcp;
using boost::system::error_code;

struct Session : std::enable_shared_from_this<Session> {
    Session(tcp::socket s) : socket_(std::move(s)) {}

    void start() {
        // TODO read loop
    }

  private:
    tcp::socket socket_;
};

class Server {
    tcp::acceptor acceptor_;

  public:
    explicit Server(asio::any_io_executor ex, uint16_t port) : acceptor_(ex, {{}, port}) {}

    void start_listening() noexcept {
        acceptor_.async_accept([this](error_code ec, tcp::socket s) {
            std::cout << "Accept " << ec.message() << std::endl;
            if (!ec.failed()) {
                std::make_shared<Session>(std::move(s))->start();
            }
            start_listening();
        });
    }
};

int main() {
    asio::io_context ioc(1);
    Server srv(ioc.get_executor(), 8080);

    srv.start_listening();

    ioc.run();
}