0

私はboost::asioの初心者で、最初の問題があります。単純なホスト リゾルバーを作成します (以下の完全なコードを参照)。

問題 1. インターネット接続が失われた場合、私のホスト リゾルバは、deadline_timer に最初に入った後に解決を停止します。私の仮定では、「localhost」はいつでも解決する必要があります。しかし、「localhost」は、google.us の解決中にタイムアウトした後に解決されません (たとえば、イーサネット ジャックを抜いたなど)。存在しない TLD を解決する場合も同じ動作です (たとえば、google.us ではなく google.usd)。

問題 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;
}
4

1 に答える 1

0

から戻った後run_onceio_serviceはおそらく「停止」状態になります。したがって、再度電話をかけるios_ptr->reset()前に電話する必要がありますrun_once()。参照からのrun_once引用:

戻り値: 実行されたハンドラーの数。ゼロの戻り値は、io_service オブジェクトが停止していることを意味します (stopped() 関数は true を返します)。run()、run_one()、poll()、または poll_one() への後続の呼び出しは、reset() への前の呼び出しがない限り、すぐに戻ります。

于 2013-09-29T13:47:09.880 に答える