2013-09-29 2 views
0

Я новичок в boost :: asio и имею первые собственные проблемы. Я создаю простой Host resolver (см. Полный код ниже).boost :: asio :: io_service destructor работает очень долгое время

Задача 1. В случае утерянного подключения к Интернету мой хост-резольвер останавливается после первого входа в deadline_timer. Мое предположение, что «localhost» необходимо разрешить в любое время. Но «localhost» не разрешаются после таймаута при разрешении google.us (например, мы отсоединили разъем Ethernet). Такое же поведение в случае разрешения неисполненного TLD (например, google.usd вместо google.us).

Задача 2. В случае утерянного подключения к Интернету деструктор io_service работает очень долго (обычно, 5 секунд).

Что случилось?

Я использую VS2012, форсирует 1,54

hostresolver.h Файл

pragma once 

#include <set> 

#include <boost/system/error_code.hpp> 
#include <boost/asio.hpp> 
#include <boost/asio/ip/basic_resolver.hpp> 
#include <boost/asio/ip/basic_resolver_iterator.hpp> 

typedef std::set<unsigned long> hostresolver_result_container; 

class hostresolver 
{ 
public: 
    hostresolver(boost::asio::io_service* io_service); 
    ~hostresolver(void); 

    boost::asio::io_service* ios_ptr; 
    boost::asio::ip::tcp::resolver resolver_; 
    boost::asio::deadline_timer timer_; 

    volatile bool is_completed; 
    bool is_timeout; 
    std::string hostname; 
    hostresolver_result_container result; 

    void on_timeout(const boost::system::error_code &err); 
    void start_resolve(const char* hostname, int timeout_seconds); 
    void finish_resolve(const boost::system::error_code& err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator); 

private: 
    void stop(); 
}; 

hostresolver.cpp Файл

#include "stdafx.h" 
#include "hostresolver.h" 

#include <boost/bind.hpp> 

hostresolver::hostresolver(boost::asio::io_service* io_service) : 
    resolver_(*io_service), timer_(*io_service), is_completed(false), is_timeout(false) 
{ 
    ios_ptr = io_service; 
} 

hostresolver::~hostresolver(void) 
{ 
} 

void hostresolver::start_resolve(const char* hostname, int timeout_second) 
{ 
    this->hostname.assign(hostname); 

    timer_.expires_from_now(boost::posix_time::seconds(timeout_second)); 
    timer_.async_wait(boost::bind(&hostresolver::on_timeout, this, _1)); 

    boost::asio::ip::tcp::resolver::query query(hostname, "http"); 
    resolver_.async_resolve(query, 
          boost::bind(&hostresolver::finish_resolve, this, 
          boost::asio::placeholders::error, 
          boost::asio::placeholders::iterator)); 

    do 
    { 
     ios_ptr->run_one(); 
    } 
    while (!is_completed); 
} 

void hostresolver::stop() 
{ 
    resolver_.cancel(); 
    timer_.cancel(); 
    is_completed = true; 
} 

void hostresolver::on_timeout(const boost::system::error_code &err) 
{ 
    if ((!err) && (err != boost::asio::error::operation_aborted)) 
    { 
     is_timeout = true; 
     stop(); 
    } 
} 

void hostresolver::finish_resolve(const boost::system::error_code& err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) 
{ 
    if (!err) 
    { 
     while (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) 
     { 
      boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; 
      if (endpoint.address().is_v4()) 
      { 
       result.insert(endpoint.address().to_v4().to_ulong()); 
      } 
      endpoint_iterator++; 
     } 
    } 

    stop(); 
} 

main.cpp Файл

#include "stdafx.h" 

#include "hostresolver.h" 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    boost::asio::io_service ios; 

    for (int i = 0; i < 2; i++) 
    { 
     std::cout << "iteration: " << i << std::endl; 

     { 
      hostresolver hres(&ios); 
      hres.start_resolve("localhost", 1); 
      if (hres.result.size() == 0) 
       std::cout << "failed" << std::endl; 
     } 

     { 
      hostresolver hres(&ios); 
      hres.start_resolve("google.usd", 1); 
     } 
    } 


    return 0; 
} 

ответ

0

После возвращения из run_once, io_service, скорее всего, войдет в состояние «остановлено». Таким образом, перед вызовом run_once() вы должны позвонить по телефону ios_ptr->reset(). Цитирование из run_once ссылки:

Return Value: The number of handlers that were executed. A zero return value implies that the io_service object is stopped (the stopped() function returns true). Subsequent calls to run(), run_one(), poll() or poll_one() will return immediately unless there is a prior call to reset().

+0

io_service :: сброс должен вызываться перед любой второй или более поздней версии набора призываний прогона(), run_one(), опрос (или) poll_one() , – user1215838

+0

@ user1215838 «... когда предыдущий вызов этих функций возвращался из-за остановки или прекращения работы io_service» –

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