2016-11-24 133 views
1

在我開始之前,我只是想嘗試一些東西。我還不知道我是否想做一個大項目。Boost ASIO socket io_service.run blocking

我嘗試使用Boost創建TCP套接字服務器,因爲它比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個多小時,我試過一百萬的東西,沒有什麼工作。我試圖把它放在一個線程中,導致我處於例外狀態。或者套接字服務器本身不起作用。

用戶輸入對重新加載特定的緩存數據或關閉應用程序或類似的東西很有用。

回答

2

這是設計。

只是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?

+0

如果我這樣做,我會得到一個調試錯誤。我現在有:'std :: thread th([&] {io_service.run();});'我試着做'th.detach()',但是它給出了錯誤。沒有分離,我也會得到錯誤。 –

+2

「錯誤」。真。如果你不確定如何在C++ 11中使用線程,那麼'std :: thread'的文檔會有所幫助(這就是爲什麼我有'//例子'註釋,你必須完成它) – sehe

+0

yes,調試錯誤。 –