Boost asio TCP async server not async?

前端 未结 2 706
礼貌的吻别
礼貌的吻别 2020-12-21 04:27

I am using the code provided in the Boost example.

The server only accepts 1 connection at a time. This means, no new connections until the current one is closed.

2条回答
  •  情书的邮戳
    2020-12-21 05:09

    Both the original code and the modified code are asynchronous and accept multiple connections. As can be seen in the following snippet, the async_accept operation's AcceptHandler initiates another async_accept operation, forming an asynchronous loop:

            .-----------------------------------.
            V                                   |
    void server::do_accept()                    |
    {                                           |
      acceptor_.async_accept(...,               |
          [this](boost::system::error_code ec)  |
          {                                     |
            // ...                              |
            do_accept();  ----------------------'
          });
    }
    

    The sleep() within the session's ReadHandler causes the one thread running the io_service to block until the sleep completes. Hence, the program will be doing nothing. However, this does not cause any outstanding operations to be cancelled. For a better understanding of asynchronous operations and io_service, consider reading this answer.


    Here is an example demonstrating the server handling multiple connections. It spawns off a thread that creates 5 client sockets and connects them to the server.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using boost::asio::ip::tcp;
    
    class session
      : public std::enable_shared_from_this
    {
    public:
      session(tcp::socket socket)
        : socket_(std::move(socket))
      {
      }
    
      ~session()
      {
        std::cout << "session ended" << std::endl;
      }
    
      void start()
      {
        std::cout << "session started" << std::endl;
        do_read();
      }
    
    private:
      void do_read()
      {
        auto self(shared_from_this());
        socket_.async_read_some(boost::asio::buffer(data_, max_length),
            [this, self](boost::system::error_code ec, std::size_t length)
            {
              if (!ec)
              {
                do_write(length);
              }
            });
      }
    
      void do_write(std::size_t length)
      {
        auto self(shared_from_this());
        boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
            [this, self](boost::system::error_code ec, std::size_t /*length*/)
            {
              if (!ec)
              {
                do_read();
              }
            });
      }
    
      tcp::socket socket_;
      enum { max_length = 1024 };
      char data_[max_length];
    };
    
    class server
    {
    public:
      server(boost::asio::io_service& io_service, short port)
        : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
          socket_(io_service)
      {
        do_accept();
      }
    
    private:
      void do_accept()
      {
        acceptor_.async_accept(socket_,
            [this](boost::system::error_code ec)
            {
              if (!ec)
              {
                std::make_shared(std::move(socket_))->start();
              }
    
              do_accept();
            });
      }
    
      tcp::acceptor acceptor_;
      tcp::socket socket_;
    };
    
    int main(int argc, char* argv[])
    {
      try
      {
        if (argc != 2)
        {
          std::cerr << "Usage: async_tcp_echo_server \n";
          return 1;
        }
    
        boost::asio::io_service io_service;
    
        auto port = std::atoi(argv[1]);
        server s(io_service, port);
    
        boost::thread client_main(
            [&io_service, port]
            {
              tcp::endpoint server_endpoint(
                  boost::asio::ip::address_v4::loopback(), port);
    
              // Create and connect 5 clients to the server.
              std::vector> clients;
              for (auto i = 0; i < 5; ++i)
              {
                  auto client = std::make_shared(
                      std::ref(io_service));
                  client->connect(server_endpoint);
                  clients.push_back(client);
              }
    
              // Wait 2 seconds before destroying all clients.
              boost::this_thread::sleep(boost::posix_time::seconds(2));
            });
    
       io_service.run();
       client_main.join();
      }
      catch (std::exception& e)
      {
        std::cerr << "Exception: " << e.what() << "\n";
      }
    
      return 0;
    }
    

    The output:

    session started
    session started
    session started
    session started
    session started
    session ended
    session ended
    session ended
    session ended
    session ended
    

提交回复
热议问题