Frage

In my question. I am a client and my purpose is only to write at server whenever required not everytime.

I have one singleton class(Caller class) in which I call my client program(Client) to write any message on server and then calling boost::asio::io_service::run through one thread . My client program(Client) is also singleton class.

My program works fine if server is already running. Because client will connect to server in first instance. But if server restarts or not running then fist I have to check whenever server is running or not before writing the message.

To check each time whether server is available or not I have to call Caller::run() and running io_service.

Without running io_service I can't check whether server is running or not as I am using all sync in my program. Everything is in async (asycn connect, sync write)

My problem is that sometime my program goes to in +D1 state(Uninterruptible sleep) and then I am not able to close my program. Is this due to io_service() ?

How can I check whether server is on or not without running 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;
  } 

Can I design in this way that I just write to the server and no need to run io_service again and again. or do I need to call io_service::reset() Am I using work in correct way ?

How can I stop or abort this gracefully ? by calling io_servie::stop or joining this thread ?

War es hilfreich?

Lösung

The typical methodology to detect connection validity is to perform an async_read() after connecting successfully. When async_read() callback indicates the boost::asio::error::eof error, your application should react appropriately:

  1. reconnect, perhaps with a timeout delay
  2. terminate gracefully
  3. abort

It sounds like you need option #1. When written correctly, your application should only need to invoke io_service::run() once, the event loop will constantly have work to do.


If you don't want to read from the socket to detect closure, instantiate a work object and keep it in scope for the duration of your program. This will ensure the io_service always has work to do. When your async_write completion handler is invoked with an error, react as necessary for your application as suggested previously.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top