为什么在asio的示例中,tcp接受器模式使用shared_pointer模型包装堆套接字,而udp使用堆栈套接字? [英] Why in asio's example the tcp acceptor pattern uses shared_pointer model wrapping heap socket, while udp use stack socket?

查看:63
本文介绍了为什么在asio的示例中,tcp接受器模式使用shared_pointer模型包装堆套接字,而udp使用堆栈套接字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

源代码: https://think-async.com/Asio/asio-1.18.0/doc/asio/tutorial/tutdaytime7/src.html

tcp_server显示了在堆上使用套接字的意图,该套接字由名为tcp_connection的类型包装.

tcp_server shows an intention to use socket on the heap, wrapped by a type called tcp_connection.

class tcp_server
{
private:
  void start_accept()
  {
    tcp_connection::pointer new_connection =
      tcp_connection::create(io_context_);

    acceptor_.async_accept(new_connection->socket(),
        boost::bind(&tcp_server::handle_accept, this, new_connection,
          asio::placeholders::error));
  }

  void handle_accept(tcp_connection::pointer new_connection,
      const asio::error_code& error)
  {
    if (!error)
    {
      new_connection->start();
    }

    start_accept();
  }
  ...

套接字堆对象由 enable_shared_from_this (也称为 shared_ptr

socket heap objects are managed by enable_shared_from_this aka shared_ptr

class tcp_connection
  : public boost::enable_shared_from_this<tcp_connection>
{
public:
  typedef boost::shared_ptr<tcp_connection> pointer;

  static pointer create(asio::io_context& io_context)
  {
    return pointer(new tcp_connection(io_context));
  }

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

  void start()
  {
    message_ = make_daytime_string();

    asio::async_write(socket_, asio::buffer(message_),
        boost::bind(&tcp_connection::handle_write, shared_from_this()));
  }
  ...

而udp服务器仅使用成员套接字.

While udp server just use member socket.

class udp_server
{
public:
  udp_server(asio::io_context& io_context)
    : socket_(io_context, udp::endpoint(udp::v4(), 13))
  {
    start_receive();
  }

private:
  void start_receive()
  {
    socket_.async_receive_from(
        asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          asio::placeholders::error));
  }

  void handle_receive(const asio::error_code& error)
  {
    if (!error)
    {
      boost::shared_ptr<std::string> message(
          new std::string(make_daytime_string()));

      socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
          boost::bind(&udp_server::handle_send, this, message));

      start_receive();
    }
  }

  void handle_send(boost::shared_ptr<std::string> /*message*/)
  {
  }

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array<char, 1> recv_buffer_;
};

我的问题是为什么tcp接受器和udp套接字示例选择不同的方法?

My question is why tcp acceptor and udp socket examples choose different approaches?

推荐答案

共享指针用于管理连接的生存期.

The shared pointer is there to manage the lifetime of the connection.

对于TCP,更常见的是具有多个连接,这会导致您可能会拥有多个具有不相关生存期的连接实例.

In the case of TCP it is more common to have multiple connections which leads to a situation where you will likely have multiple connections instances with unrelated lifetimes.

UDP是无连接的,并且多次用于单发消息.

UDP is connection-less and many times is used for one-shot messages.

实际上,您可以想出将共享指针与UDP一起使用的方案(例如,通过逻辑连接",例如通过UDP传输音频).

In fact you can come up with scenarios where you'd use shared pointers with UDP (e.g. with "logical connections", such as streaming audio over UDP).

此外,相反,您可以以不同的方式解决生命周期难题(无论TCP/UDP如何).例如,在这里我使用了 std :: list (出于参考稳定性)明智地对其进行单线程访问:

Also, conversely you CAN solve the lifetime puzzle differently (regardless of TCP/UDP). For example here I used a std::list (for reference stability) judicious single-threaded access to it: How to pass a boost asio tcp socket to a thread for sending heartbeat to client or server ¹

¹我以前在此答案中将其与shared_ptr方法进行了比较:

¹ I previously compared that to a shared_ptr approach in this answer: How to eliminate crashes when destroying boost::asio entities on fly?, which might interest you as well

这篇关于为什么在asio的示例中,tcp接受器模式使用shared_pointer模型包装堆套接字,而udp使用堆栈套接字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆