其他分享
首页 > 其他分享> > c-使用Boost :: asio触发写入

c-使用Boost :: asio触发写入

作者:互联网

我有一些要制作TCP客户端的软件.我不知道这是否是最好的体系结构,但是在我的软件中,我产生了一个将用于网络I / O的线程.如果有更好的架构,我将不胜感激一些建议和建议.

这两个线程都引用了boost :: asio :: io_service对象和一个封装套接字对象的Session对象. sesson对象大致如下:

  class Session
  {
  public:

  Session(
    boost::asio::io_service & io_service,
    std::string const & ip_address,
    std::string const & port)
  : io_service_(io_service),
    resolver_(io_service),
    socket_(io_service),
    ip_address_(ip_address),
    port_(port),
  {}

  virtual void start();
  virtual ~Session();
  virtual void stop();
  void write(std::string const & msg);

  void handle_resolve(
    const boost::system::error_code & error,
    boost::asio::ip::tcp::resolver::iterator endpoint_itr);

  void handle_connect(
    const boost::system::error_code & error,
    boost::asio::ip::tcp::resolver::iterator endpoint_itr);

  void handle_close();
  void handle_write(const boost::system::error_code & error);

private:
  boost::asio::io_service & io_service_;
  boost::asio::ip::tcp::resolver resolver_;
  boost::asio::ip::tcp::socket socket_;
  std::string ip_address_;
  std::string port_;
};

在I / O线程运行循环中,将调用连接到服务器的会话对象的start()方法. (顺便说一句,有效).然后,线程位于一个循环中,该循环在I / O服务对象[io_service_.run()]上调用run()方法以触发事件.

主线程要发送数据时,将调用会话的write()方法,会话对象将调用boost :: async_write并写入要写入的数据,然后调用作为会话对象成员的回调方法(handle_write).

当我有I / O线程连接到服务器时,我无法触发handle_write方法.我已经验证主线程正在调用会话对象并在套接字上执行async_write().只是永远不会触发回调.我也没有在服务器端或tcpdump的网络上看到任何数据.

知道我的问题可能在哪里吗?有没有更好的方法来组织架构?最重要的是,我不想阻塞执行I / O的主线程.

这是从主线程产生io线程的代码(对空格表示歉意):

    boost::asio::io_service io_service;
    boost::shared_ptr<Session> session_ptr;
    boost::thread io_thread;
    ....
    session_ptr.reset(
      new Session::Session(
                io_service,
                std::string("127.0.0.1"),
                std::string("17001")));

    // spawn new thread for the network I/O endpoint
    io_thread = boost::thread(
      boost::bind(
        &Session::start,
        session_ptr_.get()));

start()方法的代码如下:

    void Session::start()
    {
      typedef boost::asio::ip::tcp tcp;

      tcp::resolver::query query(
          tcp::v4(),
          ip_address_,
          port_);  

      resolver_.async_resolve(
          query,
          boost::bind(
              &Session::handle_resolve,
              this,
              boost::asio::placeholders::error,
              boost::asio::placeholders::iterator));

      while(1){ // improve this later
        io_service_.run();
      }
    }

解析程序的回调:

    void Session::handle_resolve(
        const boost::system::error_code & error,
        boost::asio::ip::tcp::resolver::iterator endpoint_itr)
    {
      if (!error)
      {
        boost::asio::ip::tcp::endpoint endpoint = *endpoint_itr;
        socket_.async_connect(
            endpoint,
            boost::bind(
              &Session::handle_connect,
              this,
              boost::asio::placeholders::error,
              ++endpoint_itr));
      }
      else
      {
        std::cerr << "Failed to resolve\n";
        std::cerr << "Error: " << error.message() << std::endl;
      }
    }

连接的回调:

    void Session::handle_connect(
        const boost::system::error_code & error,
        boost::asio::ip::tcp::resolver::iterator endpoint_itr)
    {
      typedef boost::asio::ip::tcp tcp;

      if (!error)
      {
        std::cerr << "Connected to the server!\n";
      }
      else if (endpoint_itr != tcp::resolver::iterator())
      {
        socket_.close();
        socket_.async_connect(
            *endpoint_itr,
            boost::bind(
              &Session::handle_connect,
              this,
              boost::asio::placeholders::error,
              ++endpoint_itr));
      }
      else
      {
        std::cerr << "Failed to connect\n";
      }

    }

主线程可以调用的write()方法发送帖子以异步方式发送.

    void Session::write(
        std::string const & msg)
    {
      std::cout << "Write: " << msg << std::endl;
      boost::asio::async_write(
          socket_,
          boost::asio::buffer(
              msg.c_str(),
              msg.length()),
          boost::bind(
              &Session::handle_write,
              this,
              boost::asio::placeholders::error));     
    }

最后,写完成回调:

    void Session::handle_write(
        const boost::system::error_code & error)
    {
      if (error)
      {
         std::cout << "Write complete with errors !!!\n";
      }
      else
      {
         std::cout << "Write complete with no errors\n";
      }        
    }

解决方法:

看起来您的io服务将在连接后耗尽,然后您只需再次调用io_service :: run即可?看起来好像在while循环中调用了run,但是我看不到任何地方可以重置的调用.您需要先调用io :: service :: reset,然后再在同一io_service上运行.

从结构上讲,最好将work添加到io_service,然后您无需在循环中调用它,并且一旦调用io_service :: stop将退出运行.

标签:asynchronous,boost,boost-asio,c
来源: https://codeday.me/bug/20191023/1913312.html