如何为Boost.Asio设计自定义IO对象 [英] How to design a custom IO object for Boost.Asio

查看:212
本文介绍了如何为Boost.Asio设计自定义IO对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基类(DeviceBase),它表示要与之通信的嵌入式设备.可以通过多种方式访问​​该设备,包括USB和TCP套接字.此外,还有一个适用于文件的模拟实现.

I have an base class (DeviceBase) representing an embedded device, with which I want to communicate. The device can be accessed in various ways, including USB and TCP sockets. Additionally, there is a mock implementation which works on files.

直到现在,我仅使用了同步读/写调用,并且所有实现都是从基类派生的类,而这些类重写了读/写功能.这使我可以使用多态指针和容器来提供与设备无关的对应用程序逻辑的访问.

Until now, I have only used synchronous read/write calls, and all the implementations are simply classes derived from the base class, overriding the read/write functions. This allows me to use polymorphic pointers and containers to provide implementation-independent access to the device to the application's logic.

现在,我想使用Boost.Asio来启用简单的异步IO. 我在 http://www.highscore.de/cpp/boost/asio中找到了该指南. html 描述了如何编写自己的扩展名,但已相当简化,我偶然发现了此处未讨论的一些问题.

Now i want to use Boost.Asio to enable simple async IO. I have found this guide http://www.highscore.de/cpp/boost/asio.html describing how to write your own extensions, but it is quite simplified, and I have stumbled upon some issues which aren't discussed there.

  • 当前,我所有的实现都有不同的构造函数(显然,由于寻址/初始化设备连接的方式不同).指南中介绍的实现类是由io_service构造的,这意味着用户无法将参数传递给构造函数.

  • Currently, all my implementations have different constructors (obviously, because of the different ways of addressing/initializing the device connection). The implementation class presented in the guide is constructed by the io_service, which means, the user can't pass arguments to the constructor.

指南中的示例以custom_io_object<implementation>的形式提供了一个模板类,该模板类将防止使用多态指针,因为现在对于不同种类的IO对象没有通用的基类.

The example in the guide provides a template class in the form of custom_io_object<implementation>, which would prevent the usage of polymorphic pointers, because now there is no common base class to the different kinds of IO objects.

是否有任何形式的文档或任何有关Boost.Asio扩展设计的书籍? 我会忽略某些东西吗?

Is there any form of documentation, or any books which discuss the design of Boost.Asio extensions? Do I overlook something?

推荐答案

听起来基于继承的解决方案可能更适合您.

It sounds like an inheritance based solution may be more appropriate for you.

以下是使用boost::signals2表示收到的消息的示例基类:

Here’s an example base class using boost::signals2 to signal a received message:

class Connection
{
public:

  typedef boost::signals2::signal<void (const std::vector<char>&)>
     PacketReceived;

protected:
  PacketReceived packet_received_;
  size_t max_rx_packet_size_;
  std::vector<char> read_buffer_;
  std::deque<std::vector<char> > tx_queue_;

  void read_handler(boost::system::error_code const& error,
                    size_t bytes_transferred)
  {
    if (boost::asio::error::operation_aborted != error)
    {
      if (error)
        ; // TODO handle the error, it may be a disconnect.
      else
      {
        read_buffer_.resize(bytes_transferred);
        packet_received_(read_buffer_);
        enable_reception(max_rx_packet_size_);
      }
    }
  }

  void write_handler(boost::system::error_code const& error,
                     size_t bytes_transferred)
  {
    if (boost::asio::error::operation_aborted != error)
    {
      tx_queue_.pop_front();
      if (error)
        ; // TODO handle the error, it may be a disconnect.
      else
        if (!tx_queue_.empty())
          transmit();
    }
  }

  virtual void receive() = 0;

  virtual void transmit() = 0;

  explicit Connection() :
    packet_received_(),
    max_rx_packet_size_(),
    read_buffer_(),
    tx_queue_()
  {}

public:

  virtual void close() = 0;

  virtual ~Connection()
  {}

  void connectPacketReceived(const PacketReceived::slot_type& slot)
  { packet_received_.connect(slot); }

  void enable_reception(size_t max_rx_packet_size)
  {
    max_rx_packet_size_ = max_rx_packet_size;
    receive();
  }

  const std::vector<char>& read_buffer() const
  { return read_buffer_; }

#if defined(BOOST_ASIO_HAS_MOVE)
  void send(std::vector<char>&& packet )
#else
  void send(const std::vector<char>& packet )
#endif
  {
    bool queue_empty(tx_queue_.empty());
    tx_queue_.push_back(packet);
    if (queue_empty)
      transmit();
  }
};

这是实现SSL套接字的类的概述:

And here's the outline of a class to implement an SSL socket:

class SslConnection :
    public Connection,
    public boost::enable_shared_from_this<SslConnection>
{
  boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket_;

  virtual void receive()
  {
    ssl_socket_.async_read_some(boost::asio::buffer(read_buffer_),
         boost::bind(&SslConnection::read_handler, shared_from_this(),
                     boost::asio::placeholders::error,
                     boost::asio::placeholders::bytes_transferred));
  }

  virtual void transmit()
  {
    boost::asio::async_write(ssl_socket_,
                             boost::asio::buffer(tx_queue_.front()),
         boost::bind(&SslConnection::write_handler, shared_from_this(),
                     boost::asio::placeholders::error,
                     boost::asio::placeholders::bytes_transferred));
  }

  SslConnection(boost::asio::io_service&   io_service,
                boost::asio::ssl::context& ssl_context) :
    Connection(),
    ssl_socket_(io_service, ssl_context)
  {}

public:

  static boost::shared_ptr<SslConnection> create
                     (boost::asio::io_service&   io_service,
                      boost::asio::ssl::context& ssl_context)
  {
    return boost::shared_ptr<SslConnection>
        (new SslConnection(io_service, ssl_context));
  }

  virtual void close()
  {
    boost::system::error_code ignoredEc;
    ssl_socket_.lowest_layer().close(ignoredEc);
  }
};

这篇关于如何为Boost.Asio设计自定义IO对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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