簡體   English   中英

同一Boost Tcp套接字對象上的多個連接

[英]Multiple connections on the same boost tcp socket object

在此示例(async_tcp_echo_server.cpp)中

#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>

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

class session
  : public std::enable_shared_from_this<session>
{
public:
  session(tcp::socket socket)
    : socket_(std::move(socket))
  {
  }

  void start()
  {
    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<session>(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 <port>\n";
      return 1;
    }

    boost::asio::io_service io_service;

    server s(io_service, std::atoi(argv[1]));

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

  return 0;
}

多個會話使用相同的boost::ip::tcp::socket對象。 do_accept()函數內部,每次傳入連接時,我們都在創建一個新的會話對象,並通過rvalue引用(即std::move()socket_傳遞給該對象。

假設我們有兩個活動的連接(S1和S2)。 結構大致如下所示

                           Server
                             |
                             |_ socket_
                                  /\
                                 /  \
                                /    \
                               S1    S2

因此,S1和S2都將使用相同的socket_從網絡讀取消息/向網絡寫入消息。

我對此有兩個問題:

  1. 對於第一個連接,一切都很好,但是為什么第二個連接應該可以正常工作呢? 我們不是已經將socket_的所有權socket_到了第一次會話嗎?

  2. 如何確保將回復發送到正確的客戶端? 每當套接字上有東西到達時,兩個async_read_some任何一個都不會觸發嗎?

對於第一個連接,一切都很好,但是為什么第二個連接應該可以正常工作呢? 我們不是已經將socket_的所有權轉移到了第一次會話嗎?

從插槽中移出后,該插槽實際上是“空”或“新創建的”。 這就是為什么這樣。

不,套接字對象不會“神奇地”與移動的實例共享身份。 實際上,身份只不過是底層套接字句柄,而后者顯然是不共享的。

但是在第二個連接的情況下會發生什么,因為我們在所有連接中都使用相同的套接字?

你不是。 您沒有使用相同的套接字句柄。 您也沒有使用相同的asio::ip::tcp::socket對象實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM