简体   繁体   中英

Boost ASIO socket io_service.run blocking

Before I start, I just was trying something out. I don't know yet if I want to do a big project.

I tried making a TCP Socket Server with Boost as it's much easier than winsock. At least, so I thought, but it doesn't work how I want it. What should happen:

  1. Read configuration
  2. Start TCP Socket Server
  3. Run _acceptor.async_accept
  4. Run io_service.run

Now, I got to the point my socket server works and accepts connections. However, I cannot do user input anymore as io_service.run blocks the rest of my server. I must be doing something wrong.

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;
}

I have searched for more than 5 hours, I tried a million things, nothing work. I tried putting it in a thread, resulting me in an exception. Or the socket server itself didn't work.

The user input is useful to reload certain cached data or close the application or something like that.

This is by design.

Just run the service on a separate thread.

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

Beware of thread synchronization on shared resources then.

io_service is thread safe (except for special operations like construction, destruction, reset). So, if you must perform tasks that need synchronization it would be easiest to post() it to the service .

As long as you have only 1 thread run -ning the particular io_service instance, you don't need additional synchronization (what is known as a logical or implicit strand ¹).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM