2013-04-12 1 views
1

В строке 67 У меня есть кодC++: BOOST-ASIO read_handler() не работает должным образом?

void session::read_handler(const boost::system::error_code& ec, std::size_t bytes_transferred) 
{ 
     std::cout<<bytes_transferred<<std::endl; 
} 

который должен быть запрошен каждый раз, когда сервер получает пакет в классе сессии, но по какой-то причине функция никогда не вызывается. io_service.run(); вызывается в int main() для read_handler(). Код в основном является примером на сайте Boost для асинхронного сервера с добавленной мной функцией. Вот код.

#include <cstdlib> 
#include <iostream> 
#include <boost/bind.hpp> 
#include <boost/asio.hpp> 

using boost::asio::ip::tcp; 

class session 
{ 
public: 
    session(boost::asio::io_service& io_service) 
    : socket_(io_service) 
    { 
    } 

    tcp::socket& socket() 
    { 
    return socket_; 
    } 

    void start() 
    { 
    socket_.async_read_some(boost::asio::buffer(data_, max_length), 
     boost::bind(&session::handle_read, this, 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 
    } 
void read_handler(const boost::system::error_code& ec, std::size_t bytes_transferred); 


private: 
    void handle_read(const boost::system::error_code& error, 
     size_t bytes_transferred) 
    { 
    if (!error) 
    { 
     boost::asio::async_write(socket_, 
      boost::asio::buffer(data_, bytes_transferred), 
      boost::bind(&session::handle_write, this, 
      boost::asio::placeholders::error)); 
    } 
    else 
    { 
     delete this; 
    } 
    } 

    void handle_write(const boost::system::error_code& error) 
    { 
    if (!error) 
    { 
     socket_.async_read_some(boost::asio::buffer(data_, max_length), 
      boost::bind(&session::handle_read, this, 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 
    } 
    else 
    { 
     delete this; 
    } 
    } 

    tcp::socket socket_; 
    enum { max_length = 1024 }; 
    char data_[max_length]; 
}; 
void session::read_handler(const boost::system::error_code& ec, std::size_t bytes_transferred) 
{ 
     std::cout<<bytes_transferred<<std::endl; 
} 

class server 
{ 
public: 
    server(boost::asio::io_service& io_service, short port) 
    : io_service_(io_service), 
     acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) 
    { 
    start_accept(); 
    } 


private: 
    void start_accept() 
    { 
    session* new_session = new session(io_service_); 
    acceptor_.async_accept(new_session->socket(), 
     boost::bind(&server::handle_accept, this, new_session, 
      boost::asio::placeholders::error)); 
    } 

    void handle_accept(session* new_session, 
     const boost::system::error_code& error) 
    { 
    if (!error) 
    { 
     new_session->start(); 
    } 
    else 
    { 
     delete new_session; 
    } 

    start_accept(); 
    } 

    boost::asio::io_service& io_service_; 
    tcp::acceptor acceptor_; 
}; 

int main() 
{ 
    try 
    { 
    boost::asio::io_service io_service; 
    server s(io_service, 4000); 

    io_service.run(); 
    } 
    catch (std::exception& e) 
    { 
    std::cerr << "Exception: " << e.what() << "\n"; 
    } 

    return 0; 
} 

ответ

1

сессия :: read_handler (...) не был установлен в качестве обработчика.

handle_accept() вызывается, потому что он установлен в качестве обработчика:

acceptor_.async_accept(new_session->socket(), 
     boost::bind(&server::handle_accept, this, new_session, 
      boost::asio::placeholders::error)); 

handle_read (...) называется bacause он установлен в качестве обработчика:

socket_.async_read_some(boost::asio::buffer(data_, max_length), 
      boost::bind(&session::handle_read, this, 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 

То же самое для handle_write (. ..) - задается функцией handle_read.

Но read_handler не установлен. Вместо этого используйте handle_read. Или вызовите read_handler из handle_read.

void handle_read(const boost::system::error_code& error, 
     size_t bytes_transferred) 
    { 
    if (!error) 
    { 
     std::cout<<bytes_transferred<<std::endl; // try this. 
     read_handler(error, bytes_transferred); // OR this. 

     boost::asio::async_write(socket_, 
      boost::asio::buffer(data_, bytes_transferred), 
      boost::bind(&session::handle_write, this, 
      boost::asio::placeholders::error)); 
    } 
    else 
    { 
     delete this; 
    } 
    } 
1

функция не получает не вызывается, потому что ни один не называть его ни передать его в качестве обработчика к одной из функций асинхронными.

вы можете видеть обработчики как состояния конечного автомата, а async_ * вызывает переходы между этими состояниями. ваши состояния являются следующей (начальной точкой является start_accept, вызывается из server::server:

<<start>>     --async_accept-----> <server::handle_accept> //via server::server > server::start_accept 
<server::handle_accept>  --async_read_some--> <session::handle_read> //via session::start 
<session::handle_read>  --async_write------> <session::handle_write> 
<session::handle_write>  --async_read_some--> <session::handle_read> 

Пути только для случаев без ошибок случаев ошибок тривиальны, они просто завершите программу или, в случае handle_accept просто повторите попытку. переход.

Вы можете увидеть, возможно, бесконечный цикл между handle_read и handle_write, но read_handler не является частью игры.