C 设计:多个TCP客户端,Boost ASIO和观察者

C++ Design: Multiple TCP clients, boost asio and observers

本文关键字:Boost ASIO 观察者 客户端 设计 多个 TCP      更新时间:2023-10-16

在我的系统中,我有一群TCP客户端,我对如何设计它感到有些困惑(我的大部分经验是在C中,因此不安全感(。我正在使用Boost ASIO来管理连接。这些是我拥有的组件

  • tcpstream类:Boost Asio
  • 的薄包装器
  • IPC协议,该协议通过TCP实施协议:基本上每个消息都以类型和长度字段开头因此我们可以从流中读取各个消息。
  • 处理消息的连接类
  • 监视连接的观察者类

我正在编写伪C 代码是简洁的。我想你会得到这个想法

class TCPStream {
   boost::asio::socket socket_;
public:
   template <typename F>
   void connect (F f)
   {
       socket_.connect(f);
   }
   template <typename F>
   void read (F f)
   {
      socket_.read(f);
   }
};
class IpcProtocol : public TCPStream {
public:
    template <typename F
    void read (F f)
    {
        TCPStream::read(
              [f] (buffer, err) {
                while (msg = read_indvidual_message(buffer)) {
                      // **** this is a violation of how this pattern is 
                      // supposed to work. Ideally there should a callback 
                      // for individual message. Here the same callback
                      // is called for N no. of messages. But in our case  
                      // its the same callback everytime so this should be      
                      // fine - just avoids some function calls.
                      f(msg);
                };
              };
         )
    }
};

可以说我有一堆TCP连接,还有一个处理程序类对于每个连接。让我们命名IT Connection1,Connection2 ...

class Connection {
    virtual int type() = 0;
};
class Connection1 : public Connection {
   shared_ptr<IpcProtocol> ipc_;
   int type ()
   {
       return 1;
   }
   void start ()
   {
       ipc_.connect([self = shared_from_this()](){ self->connected(); });
       ipc_.read(
            [self = shared_from_this()](msg, err) {
              if (!err)
                  self->process(msg);
              } else {
                  self->error();
              }   
            });
   }
   void connected ()
   {
       observer.notify_connected(shared_from_this());
   }
   void error ()
   {
       observer.notify_error(shared_from_this());
   }
};

此模式以一种或其他方式重复所有连接。消息由连接类本身处理。但这会让其他事件[连接,错误]与观察者。原因 -

  1. 重新启动连接,每次断开连接
  2. 一群人需要知道是否建立了连接,以便他们可以将初始请求/浓汤发送到服务器。
  3. 有一些需要根据Muliple连接的连接状态完成的事情例如:如果建立Connection1和Connection2,则启动Connection3等。

我在那里添加了一个中间观察者类,以便观察者每次重新启动时都必须直接连接到连接。每次连接中断,连接类都将被删除并创建新的连接类。

 class Listeners {
public:
    virtual void notify_error(shared_ptr<Connection>) = 0;
    virtual void notify_connect(shared_ptr<Connection>) = 0;
    virtual void interested(int type) = 0;
};

class Observer {
   std::vector<Listeners *> listeners_;
public:
   void notify_connect(shared_ptr<Connection> connection)
   {
        for (listener : listeners_) {
            if (listener->interested(connection->type())) {
                listener->notify_error(connection);
            }
        }       
   }
};

现在,这是对此作品的粗略原型。但是我想知道这个课程是否 任何好处。有多个流媒体服务器将不断产生状态,并将其发送到我的模块以H/W中的状态编程。这需要可扩展,因为将来会添加更多的客户。

线程

旧版代码每个TCP连接具有一个线程,这很好。在这里,我试图在同一线程上处理多个连接。仍然会有多个呼叫ioservice的线程。因此,观察者将在多个线程上运行。我打算每个听众都有一个静音,以免听众同时获得多个事件。

http通过TCP实现协议,因此HTTP服务器ASIO示例是设计的好起点,尤其是:HTTP Server 2HTTP Server 3HTTP Server 4

注意:连接生命周期可能是一个问题,尤其是因为您打算将类成员功能用作处理程序,请参阅此处的问题和答案:如何设计Boost :: Asio套接字或其包装器的正确发布。