2011-05-12 4 views
1

boost website에 주어진 HTTP 서버의 예제를 기반으로 HTTP 클라이언트를 빌드하고 있습니다. 이제이 코드와 다른 점은 서버 생성자를 사용하여 비동기 작업을 시작한다는 것입니다. 이것은 서버가 항상 듣기로되어 있기 때문에 의미가 있습니다. 내 클라이언트에서는 다른 한편으로는 먼저 객체를 구성한 다음 send() 함수를 끝점에 연결하여 시작하고 나중에 요청을 보내고 마지막으로 응답을 수신하려고합니다. 이것은 너무 의미가 있습니다, 안 그래요?boost :: asio를 사용할 때의 참조 문제 (아마도)

개체 (클라이언트)를 만들 때 서버 예제 (winmain.cpp)와 같은 방식으로 작업을 수행합니다. 그것은 다음과 같습니다

client c("www.boost.org); 
c.start(); // starts the io_service in a thread 
c.send(msg_); 

코드의 관련 부분은 다음과 같습니다

void enabler::send(common::geomessage& msg_) 
{ 
    new_connection_.reset(new connection(io_service_, 
     connection_manager_, 
     message_manager_, msg_ 
    )); 

    boost::asio::ip::tcp::resolver resolver(io_service_); 
    boost::asio::ip::tcp::resolver::query query(host_address, "http"); 

    resolver.async_resolve(query, boost::bind(
     &enabler::handle_resolve, 
     boost::ref(*this), 
     boost::asio::placeholders::error, 
     boost::asio::placeholders::iterator 
    )); 
} 

void enabler::run() 
{ 
    io_service_.run(); 
} 

이의 문제는 프로그램이 여기 어딘가에 붙어 도착한다는 것입니다. 마지막으로 인쇄되는 것은 "해결 호스트"입니다. 그 후 프로그램이 종료됩니다. io_service이 모든 비동기 작업이 콜백으로 반환 될 때까지 차단해야하기 때문에 왜 그런지 모르겠습니다. 그러나 함수의 호출 순서를 변경하면 작동합니다. async_resolve()에 대한 호출 직후 run()으로 전화를 걸고 내 주 프로그램에서 start()을 호출하지 않으면 작동합니다!

이 시나리오에서는 io_service 블록을 사용해야하며 서버에서 응답을받을 수 있습니다.

async_resolve()과 같은 클래스 안에서 run()을 호출한다는 점에서 뭔가가 있습니다. 이것이 사실일까요? 내가 run()라고 부를 때 주 프로그램에서 참고할 필요가 있다고 생각합니까?

저는 io_service::work을 사용하는 데 어려움을 겪었지만 프로그램이 멈추었 고 예와 비슷한 문제가 발생했습니다. 그래서 그것은 정말로 도움이되지 않습니다.

그렇다면이 권리를 얻기 위해 무엇을 할 수 있습니까? 앞서 말했듯이 클라이언트 객체를 만들고 클라이언트 클래스 내의 별도 스레드에서 항상 실행중인 io_service을 가질 수 있어야합니다. 둘째, 서버에 요청을 보내는 기능이있는 send()입니다.

답변

0

io_service를 계속 사용하려면 일부 작업이 필요하지 않은 경우 io_service::run()을 먼저 반환하지 않고 종료 할 수있는 범위의 io_service::work 개체를 구성해야합니다. 별도의 스레드에서 io_service을 실행하고 있다면 문제가 없을 것이라고 생각합니다.

코드 스 니펫으로 수행하려는 작업을 파악하는 것은 어렵습니다. 이 줄을 따라 뭔가를하고 싶다고 생각합니다.

struct client 
{ 
    io_service io_service_; 
    io_service::work* w_; 
    pthread_t main_thread_; 
    client(): w_(new io_service::work(io_service)) { ... } 
    void start() { pthread_create(&main_thread_, 0, main_thread, this); } 
    static long main_thread(void* arg) { ((client*)arg)->io_service_.run(); } 
    // release the io_service and allow run() to return 
    void stop() { delete w_; w_ = 0; pthread_join(main_thread_); } 
}; 
2

run()으로 전화하기 전에 적어도 일부 작업을 시작해야합니다. 더 이상 할 일이 없을 때 돌아옵니다.

비동기 해결을 시작하기 전에이 메서드를 호출하면 작업이 수행되지 않으므로 반환됩니다.

+0

감사합니다. async_resolve() 바로 뒤에 send() 함수에서 run()을 호출 할 수 있습니다. 그러나 문제는 run()이 이미 호출 된 경우 다시 호출하는 것이 잘못된 것입니다.현재 run()이 끝나기 전에 요청을 보낼 수 있도록 send()를 사용하고 싶습니다. io_service가 끝났는지를 결정할 수있는 방법이 있는가? 그리고 실행을 다시 호출해도 안전한지 판단 할 수 있는가? 그게 효과가 있다면 좋을 것입니다. 그 이유는 if 문에서 이것을 체크 할 수 있기 때문입니다. –

+0

당신이 실제로 사용할 수있는 것처럼 들리는 것은 run()이 무기한으로 가게하는 것입니다. 그래서 그것에 대해 걱정할 필요가 없습니까? asio 문서에는 [해당 섹션 만 있습니다] (http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.stopping_the_io_service_from_running_out_of_work). –

+0

예! 그게 정확히 내가 원하는 걸! 하지만 이미 참조한 페이지를 읽고 ioservice :: work로 작업 할 수 없습니다. 클라이언트 클래스의 private 변수로 정의 된 io_service가 있습니다. 내 run() 함수에서이 시도했다 : boost :: asio :: io_service :: work work (io_service_); io_service_.run(); 그런 다음 전체 작업을 중지하려면 io_service_.stop();을 호출해야합니다. 그 맞습니까? 왜냐하면 난 그저 일을 할 수 있기 때문이야. –

관련 문제