2016-11-24 2 views
1

Прежде чем начать, я просто что-то пытался. Я еще не знаю, хочу ли я сделать большой проект.Boost ASIO socket io_service.run блокировка

Я попытался сделать TCP Socket Server с Boost, поскольку это намного проще, чем winsock. По крайней мере, так я думал, но это не работает, как я этого хочу. Что должно произойти:

  1. Считать конфигурацию
  2. Start TCP Сокет сервера
  3. Run _acceptor.async_accept
  4. Run 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 часов, я попробовал миллион вещей, ничего работать. Я попытался поместить его в поток, в результате чего я стал исключением. Или сам сокет-сервер не работал.

Пользовательский ввод полезен для перезагрузки определенных кешированных данных или закрытия приложения или чего-то подобного.

ответ

2

Это по дизайну.

Всего run обслуживание по отдельной теме.

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

Остерегайтесь синхронизации потоков на общих ресурсах.

io_service является потокобезопасным (за исключением специальных операций, таких как строительство, уничтожение, сброс). Итак, если вы должны выполнять задачи, требующие синхронизации, было бы проще всего post() это service.

До тех пор, пока у вас есть только одна нить run -ning конкретного io_service экземпляра, не нуждается в дополнительной синхронизации (то, что известно как логический или неявной прядь ¹).

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

+0

Если я, что я получаю ошибку отладки. У меня есть теперь: 'std :: thread th ([&] {io_service.run();});' и я пробовал делать 'th.detach()', но он дает ошибку. Без отсоединения я также получаю ошибку. –

+2

"ошибка". В самом деле.Документация для 'std :: thread' помогает, если вы не знаете, как использовать потоки в C++ 11 (вот почему у меня был комментарий' // example', вы должны его заполнить) – sehe

+0

yes, ошибка отладки , –

Смежные вопросы