ASIO io_service 多次运行的问题

Posted

技术标签:

【中文标题】ASIO io_service 多次运行的问题【英文标题】:Issue with ASIO io_service to run multiple time 【发布时间】:2013-03-12 18:58:38 【问题描述】:

在我的问题中。我是客户,我的目的只是在需要时而不是每次都在服务器上编写。

我有一个单例类(调用者类),我在其中调用我的客户端程序(客户端)在服务器上写入任何消息,并且 然后通过一个线程调用 boost::asio::io_service::run 。 我的客户端程序(Client)也是单例类。

如果服务器已经在运行,我的程序可以正常工作。因为客户端将首先连接到服务器。但是,如果服务器重新启动或没有运行,那么首先我必须在写入消息之前检查服务器是否正在运行。

要每次检查服务器是否可用,我必须调用 Caller::run() 并运行 io_service。

如果不运行 io_service,我无法检查服务器是否正在运行,因为我在程序中使用了所有同步。 一切都是异步的(异步连接,同步写入)

我的问题是有时我的程序进入 +D1 状态(不间断睡眠),然后我无法关闭我的程序。 这是由于 io_service() 造成的吗?

如何在不运行 io_service 的情况下检查服务器是否开启?

 class Caller
 
  public:

  static Caller* getInstance()
  
   static Caller Caller;
   return &Caller;
  

  void run() 
  
    pWork.reset( new boost::asio::io_service::work(io_service) );

    ////////////calling client program//////////////// 
    Client::getInstance(io_service)->start();

    thread = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));
       

  boost::asio::io_service io_service;
  boost::shared_ptr<boost::asio::io_service::work> pWork;

  boost::thread thread;

 private:
  Caller()
  
  
  ~Caller()
  
    pWork.reset();
    thread.join();
  
; 


///////////my client program (Singleton Class)//////////////////
//////message write function///////////

void Client::sendResponse(std::string& messag)                      
                                                                              
  boost::system::error_code error;                                           
  boost::asio::ip::tcp::endpoint endpoint = socket().remote_endpoint(error);    

  if ( error ) 
                                                                 
    DEBUG_2("could not write: ",boost::system::system_error(error).what());    
    this->stop(); /////this will close the socket////
    Caller::getInstance()->run();   
    //////it will call the caller program to call the  connect function of client program /////
                                                                             
  else
    boost::asio::async_write(                                                         
      _socket,                                                                      
      boost::asio::buffer( message.c_str(), message.size()),
      _strand.wrap(                                                                 
        boost::bind(                                                                
          &Client::writeHandler,                                             
          this,
          boost::asio::placeholders::error,                                         
          boost::asio::placeholders::bytes_transferred  
                                                                              


 Client *Client::getInstance(boost::asio::io_service& io_service)
  
    if (!Client)
    
      Client = new Client(io_service);
    
    return Client;
   

我可以这样设计吗,我只写到服务器,不需要一次又一次地运行 io_service。 还是我需要调用 io_service::reset() 我是否以正确的方式使用工作?

我怎样才能优雅地停止或中止这个? 通过调用 io_servie::stop 或加入这个线程?

【问题讨论】:

【参考方案1】:

检测连接有效性的典型方法是在连接成功后执行async_read()。当async_read() 回调指示boost::asio::error::eof 错误时,您的应用程序应该做出适当的反应:

    重新连接,可能有超时延迟 优雅地结束 中止

听起来您需要选项#1。如果编写正确,您的应用程序应该只需要调用一次io_service::run(),事件循环将不断有工作要做。


如果您不想通过读取套接字来检测关闭,请实例化一个 work 对象并在程序执行期间将其保持在范围内。这将确保io_service 始终有工作要做。当您的 async_write 完成处理程序因错误而被调用时,请按照之前的建议对您的应用程序做出必要的反应。

【讨论】:

1.我不能使用 async_read 因为我不需要从服务器读取。 2. 如果服务器不在,客户端将在客户端需要在服务器上写入任何消息时尝试连接到服务器,因此超时延迟是不可能的。 3. 请让我知道如何优雅地终止?通过调用 io_service::stop 或加入这个线程? 4. 如何中止? 感谢您的帮助。这意味着我只需要将 io_service 保持在范围内,每当我需要重新连接时,我只需要调用 start 函数即可从函数 Client::sendResponse(std::string& message) 连接到服务器。无需再次运行 io_service。它工作正常。谢谢

以上是关于ASIO io_service 多次运行的问题的主要内容,如果未能解决你的问题,请参考以下文章

从作为分离线程运行的 boost::asio::io_service::work 捕获异常

boost::asio::io_service 运行方法阻塞/解除阻塞时感到困惑

从多个线程调用 boost::asio::io_service 运行函数

我应该如何在 io_service 中解决这个问题?

boost::asio io_service 停止特定线程

asio::io_service 和 thread_group 生命周期问题