C ++:BOOST-ASIO read_handler()无法按预期工作?

时间:2013-04-12 09:06:41

标签: c++ boost-asio polling

在第67行,我有代码

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()调用#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; } 。代码基本上是Boost站点上的示例,用于异步服务器,我添加了该功能。这是代码。

{{1}}

2 个答案:

答案 0 :(得分: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_readhandle_write之间可能无休止的循环,但read_handler不属于游戏的一部分。

答案 1 :(得分:1)

session :: read_handler(...)未设置为处理程序。

调用handle_accept()因为它被设置为handler:

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

handle_read(...)被称为bacause,因为它被设置为handler:

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。或者从handle_read调用read_handler。

  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;
    }
  }