2013-03-12 2 views
1

В моем вопросе. Я клиент, и моя цель - писать только на сервере, когда это необходимо не каждый раз.Проблема с ASIO io_service для запуска несколько раз

У меня есть один одноэлементный класс (класс вызывающего абонента), в котором я вызываю свою клиентскую программу (Клиент) для записи любого сообщения на сервере и , затем вызывает boost :: asio :: io_service :: выполняется через один поток. Моя клиентская программа (Клиент) также является одноточечным классом.

Моя программа работает нормально, если сервер уже запущен. Поскольку клиент будет подключаться к серверу в первом экземпляре. Но если сервер перезагружается или не запускается, то кулак я должен проверять, когда сервер работает или нет, прежде чем писать сообщение.

Чтобы проверить каждый раз, доступен ли сервер или нет, мне нужно вызвать Caller :: run() и запустить io_service.

Без запуска io_service Я не могу проверить, работает ли сервер или нет, поскольку я использую всю синхронизацию в своей программе. Все в async (asycn connect, sync write)

Моя проблема в том, что когда-то моя программа переходит в состояние + 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 :: остановитесь или присоединитесь к этой теме?

ответ

1

Типичная методика определения достоверности подключения - это выполнить async_read() после успешного соединения. Когда async_read() обратного вызова указывает на ошибку boost::asio::error::eof, ваше приложение должно реагировать соответствующим образом:

  1. переподключение, возможно, с тайм-аут оттянуть
  2. прекращает грациозно
  3. прервать

Это звучит, как вам нужно вариант # 1 , При написании правильно, вашему приложению нужно будет только вызвать io_service::run() один раз, цикл событий будет постоянно работать.


Если вы не хотите читать из розетки, чтобы обнаружить замыкание, экземпляр work объекта и сохранить его в объеме в течение всего срока программы. Это обеспечит работу io_service. Когда ваш обработчик завершения async_write вызывается с ошибкой, отреагируйте, если это необходимо для вашего приложения, как было предложено ранее.

+0

1. Я не могу использовать async_read, поскольку мне не нужно читать с сервера. 2. Если сервер не включен, клиент будет пытаться подключиться к серверу всякий раз, когда клиент должен писать любое сообщение на сервере, поэтому таймаут невозможен. 3. Пожалуйста, дайте мне знать, как я могу закончить изящество? , позвонив io_service :: остановить или присоединиться к этой теме? 4. Как я могу отменить? – user1841046

+0

@ user1841046 Ответ отредактирован, чтобы ответить на ваши вопросы –

+0

Спасибо за помощь. Это означает, что мне просто нужно сохранить io_service в области видимости и всякий раз, когда мне нужно снова подключиться, мне просто нужно вызвать функцию запуска для подключения к серверу из функции Client :: sendResponse (std :: string & message). Не нужно снова запускать io_service. И работает отлично. Спасибо – user1841046

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