【问题标题】:How to start Boost echo server in a separate thread如何在单独的线程中启动 Boost echo 服务器
【发布时间】:2021-03-06 23:20:42
【问题描述】:

我使用 boost 版本 boost 1_64_0 在单独的线程中运行 Tcp 服务器

这是服务器的代码。

https://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/example/echo/async_tcp_echo_server.cpp

在主循环中,我可以像这样生成一个新线程。

int main()
{

// Run the boost echo server as a different thread
boost::asio::io_service io_service;
server server1(io_service, 1980);   
boost::thread t(boost::bind(&io_service::run, &io_service));    

// when about to close the program
io_service.stop(); // stop the server
t.join();
}

现在我已将 boost 版本更改为 boost_1_73_0,我正在使用此示例创建服务器

https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp

如何创建一个新线程?

创建新线程的现有代码出错。

  1. io_service: :: 左边必须是类/结构/联合

  2. 运行:未声明的标识符

【问题讨论】:

    标签: boost boost-asio


    【解决方案1】:

    &io_service::run 中,io_service 不是类型,而是该名称的局部变量。

    https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp开始

        io_context.run();
    

    需要像

        std::thread t([&] { io_context.run(); });
        // ...
        t.join();
    

    或者如果你坚持:

        std::thread t(boost::bind(&boost::asio::io_context::run, &io_context));
    

    我会使用线程池来简化所有复杂性¹:

        boost::asio::thread_pool io(1);
    
        server s(io.get_executor(), std::atoi(argv[1]));
    
        // ...
        io.join();
    

    需要对类接口进行简单的编辑(参见例如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";
        }
    }
    

    ¹ 参见例如Should the exception thrown by boost::asio::io_service::run() be caught?

    【讨论】:

    • 谢谢你的回答,你的回复和往常一样棒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-26
    • 1970-01-01
    相关资源
    最近更新 更多