2012-10-24 3 views
1

누군가가 boost::asioio_service::run() 메서드가 반환 할 조건을 말해 줄 수 있습니까? 문서 documentation for io_service::run()은 수행해야 할 작업 또는 전달할 처리자가있는 한 run()이 반환하지 않는다고 제안하는 것 같습니다.boost asio io_service :: run()은 'early'를 종료합니까?

내가 묻는 이유는 서버에 접속하여 http POST를 실행하는 레거시 https 클라이언트가 있기 때문입니다. 클라이언트의 관심사를 분리하는 것은 우리가 원하는 것과 약간 다릅니다. 그래서 우리는 그것에 대해 몇 가지를 바꾸고 있지만 문제가 있습니다.

지금 클라이언트는 기본적으로 서버와의 전체 프로토콜 대화를 효과적으로 유도하는 잘못된 이름의 connect() 호출을 사용합니다. connect() 호출은 boost::asio::ip::tcp::resolver 개체를 만들고이 개체에 ::async_resolve()을 호출하는 것으로 시작합니다. 이렇게하면 새로운 asio 호출이 asio 콜백 내에서 만들어지는 체인이 시작됩니다.

void connect() 
{ 
    m_resolver.async_resolve(query, bind(&clientclass::resolve_callback, this)); 
    thread = new boost::thread(bind(&boost::asio::io_service::run, m_io_service)); 
} 
void resolve_callback(error_code & e, resolver::iterator i) 
{ 
    if (!e) 
    { 
     tcp::endpoint = *i; 
     m_socket.lowest_layer().async_connect(endpoint, bind(&clientclass::connect_callback,this,_1,++i)); 
    } 
} 
void connect_callback(error_code & e, resolve::iterator i) 
{ 
    if (!e) 
    { 
     m_socket.lowest_layer().async_handshake(boost::asio::ssl::stream_base::client, 
      bind(&clientclass::handshake_callback,this,_1,++i)); 
    } 
} 
void handshake_callback(error_code &e) 
{ 
    if (!e) 
    { 
     mesg = format_hello_message(); 
     http_send(mesg, bind(&clientlass::hello_resp_handler,this,_1,_2)); 
    } 
} 
void http_send(stringstream & mesg, reply_handler handler) 
{ 
    async_write(m_socket, m_request_buffer, bind(&clientclass::write_complete_callback,this,_1,handler)); 
} 
void write_comlete_callback(error_code &e, reply_handler handler) 
{ 
    if (!e) 
    { 
     async_read_until(m_socket,m_reply_buffer,"\r\n\r\n", bind(&clientclass::handle_reply,this,handler)); 
    } 
} 
... 

어쨌든 이것은 프로토콜 대화가 완료 될 때까지 프로토콜을 통해 계속됩니다. 여기 코드에서 connect()이 주 스레드에서 실행되고있는 동안 모든 후속 콜백 및 요청은 connect()에 작성된 작업자 스레드로 되돌아오고 있음을 알 수 있습니다. 이것은 '작동하는'코드입니다.

이 체인을 끊고 외부 인터페이스를 통해 노출 시키려고하면 작동이 멈 춥니 다. 특히, handle_handshake() 전화를 clientclass 개체 외부로 호출하고 있습니다. 그런 다음 http_send()은 인터페이스의 일부이거나 외부 인터페이스에 의해 호출되며 io_service :: run()을 호출하는 새 작업자 스레드를 만듭니다. async_write()이 호출되었고 write_complete_callback()이 반환되지 않은 경우에도 io_service :: run()이 종료됩니다. 그것은 오류없이 종료되고 처리기가 발송되지 않았다고 주장하지만 여전히 수행해야 할 '작업'이 있습니까?

제가 궁금한 점은 io_service::run()의 '작업'정의가 무엇입니까? 대기중인 요청입니까? 그 이유는 io_service::run()이 기존 코드의 요청 및 응답 체인 중에 결코 반환하지 않지만 스레드를 다시 시작하고 새 체인을 시작하려고하면 거의 즉시 작업을 완료하기 전에 반환됩니다.

답변

3

run() 호출의 컨텍스트에서의 작업 정의는 해당 io_service 객체에 대한 보류중인 비동기 작업입니다. 여기에는 작업에 대한 응답으로 처리기가 호출됩니다. 따라서 한 작업의 처리기가 다른 작업을 시작하면 항상 사용할 수있는 작업이 있습니다.

또한 개체가 소멸 될 때까지 완료되지 않는 io_service에서 작업을 만드는 데 사용할 수있는 io_service::work 클래스가 있습니다.

단일 체인이 완료되면 io_service가 모든 비동기 작업을 완료하고 새 작업을 시작하지 않고 모든 핸들러가 호출되어 반환됩니다. io_service::reset()으로 전화 할 때까지 아무런 작업도 수행하지 않고 run()으로 다시 전화하면됩니다.

+0

+1 OP가 후속 실행 전에 재설정 될 가능성이 매우 높습니다. – Ralf

+0

정확히 내가하지 않았던 내용이었습니다. 나는':: reset()'호출을 추가했고, 이제는 모두 잘되었다. 감사! –

관련 문제