提升ASIO套接字io_service.run阻止

时间:2016-11-24 08:50:11

标签: c++ sockets boost boost-asio

在我开始之前,我只是想尝试一下。我还不知道我是否想做一个大项目。

我尝试使用Boost制作TCP套接字服务器,因为它比winsock容易得多。至少,所以我想,但它不起作用,我想要它。会发生什么:

  1. 阅读配置
  2. 启动TCP套接字服务器
  3. 运行_acceptor.async_accept
  4. 运行io_service.run
  5. 现在,我已经到了我的套接字服务器工作并接受连接。但是,我不能再进行用户输入,因为io_service.run会阻止我的服务器的其余部分。我一定是做错了。

    tcp_listener.h:

    #pragma once
    #include <boost/asio.hpp>
    class tcp_listener
    {
    public:
        tcp_listener(boost::asio::io_service& io_service, std::string ip, short port);
        static void start(tcp_listener* ptr);
        void start_accepting();
    private:
        boost::asio::ip::tcp::acceptor _acceptor;
        boost::asio::ip::tcp::socket _socket;
    };
    

    tcp_listener.cpp:

    #include "tcp_listener.h"
    #include "logger.h"
    #include <boost/asio.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/bind.hpp>
    #include <boost/thread.hpp>
    #include <memory>
    
    tcp_listener::tcp_listener(boost::asio::io_service& io_service, std::string ip, short port)
        : _acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::from_string(ip), port)),
          _socket(io_service)
    {
        logger::log_main("Network bound on %s.%d", _acceptor.local_endpoint().address().to_string().data(), _acceptor.local_endpoint().port());
    
        start_accepting();
    
        io_service.run();
    }
    
    void tcp_listener::start(tcp_listener* ptr)
    {
        ptr->start_accepting();
    }
    
    void tcp_listener::start_accepting()
    {
        _acceptor.async_accept(_socket, [this](boost::system::error_code ec)
        {
            if (!ec)
            {
                logger::log_main("New connection %s", _socket.remote_endpoint().address().to_string().data());
                //std::make_shared<tcp_client>(std::move(socket_))->start_receiving();
            }
            else
            {
                _acceptor.close();
            }
    
            start_accepting();
        });
    }
    

    engine.h:

    #pragma once
    #include "configuration.h"
    class engine
    {
    public:
        static void boot();
        static void destroy();
        static configuration* get_config();
    private:
        static configuration* config;
    };
    

    engine.cpp:

    #include "engine.h"
    #include "tcp_listener.h"
    #include <boost/thread.hpp>
    #include <boost/bind.hpp>
    configuration* engine::config;
    void engine::boot()
    {
        engine::config = new configuration("config.cnf");
    
        boost::asio::io_service io_service;
        tcp_listener& list = tcp_listener(io_service, engine::config->get_value("network.ip"), atoi(engine::config->get_value("network.port").data()));
    }
    
    void engine::destroy()
    {
        delete engine::config;
    }
    
    configuration* engine::get_config()
    {
        return engine::config;
    }
    

    Main.cpp的:

    #include "engine.h"
    #include <iostream>
    
    int main()
    {
        engine::boot();
    
        for (;;)
        {
            std::string input;
            std::cin >> input;
    
            if (input == "exit")
            {
                engine::destroy();
    
                break;
            }
        }
    
        return 0;
    }
    

    我搜索了超过5个小时,我尝试了一百万件事,没什么用。我尝试将它放在一个线程中,导致我出现异常。或者套接字服务器本身不起作用。

    用户输入对于重新加载某些缓存数据或关闭应用程序或类似内容非常有用。

1 个答案:

答案 0 :(得分:2)

这是设计的。

在单独的线程上只需run服务。

 std::thread th([&] { io_service.run(); }); // example

然后注意共享资源上的线程同步。

io_service是线程安全的(除了构造,破坏,重置等特殊操作)。因此,如果您必须执行需要同步的任务,最简单的方法是post() service

只要您只有1个线程run - 在特定的io_service实例中,您就不需要额外的同步(所谓的逻辑或隐式链¹)。

¹documentation