【问题标题】:Boost ASIO socket io_service.run blockingBoost ASIO socket io_service.run 阻塞
【发布时间】:2016-11-24 08:50:11
【问题描述】:

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

我尝试使用 Boost 制作 TCP Socket 服务器,因为它比 winsock 容易得多。至少,我是这么想的,但它并没有按照我想要的方式工作。应该发生什么:

  1. 读取配置
  2. 启动 TCP 套接字服务器
  3. 运行 _acceptor.async_accept
  4. 运行 io_service.run

现在,我的套接字服务器可以工作并接受连接了。但是,我不能再进行用户输入,因为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 个小时,我尝试了 100 万件事情,但没有任何效果。我试着把它放在一个线程中,导致我出现异常。或者套接字服务器本身不起作用。

用户输入对于重新加载某些缓存数据或关闭应用程序或类似操作很有用。

【问题讨论】:

    标签: c++ sockets boost boost-asio


    【解决方案1】:

    这是设计使然。

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

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

    那么请注意共享资源上的线程同步。

    io_service 是线程安全的(构造、销毁、重置等特殊操作除外)。因此,如果您必须执行需要同步的任务,最简单的方法是将post() 发送到service

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

    ¹Why do I need strand per connection when using boost::asio?

    【讨论】:

    • 如果我这样做,我会得到一个调试错误。我现在有:std::thread th([&amp;] { io_service.run(); });,我尝试做th.detach(),但它给出了错误。如果没有分离,我也会收到错误。
    • “错误”。真的。如果您不确定如何在 c++11 中使用线程,std::thread 的文档会有所帮助(这就是我有 // example 评论的原因,您必须完成它)
    • 来吧。我不是通灵者。很可能您要么在向服务添加工作之前启动线程,要么在生命周期结束之前忘记加入线程。或两者。你可以用你喜欢的任何方式开始一个线程。有许多。无论如何,大多数 Boost Asio 示例都展示了如何做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2011-03-31
    • 1970-01-01
    相关资源
    最近更新 更多