C++ C++;设计:多个TCP客户端、boost asio和观察器
在我的系统中,我有一大堆TCP客户机,我对如何设计它有点困惑[我的大部分经验都是用C编写的,因此不安全]。我正在使用boost ASIO管理连接。这些是我拥有的组件C++ C++;设计:多个TCP客户端、boost asio和观察器,c++,design-patterns,boost-asio,C++,Design Patterns,Boost Asio,在我的系统中,我有一大堆TCP客户机,我对如何设计它有点困惑[我的大部分经验都是用C编写的,因此不安全]。我正在使用boost ASIO管理连接。这些是我拥有的组件 TCPStream类:boost asio上的薄包装器 IPC协议,通过TCP实现协议: 基本上,每条消息都以类型和长度字段开头 因此,我们可以从流中读取单个消息 处理消息的连接类 监视连接的观察者类 我编写的是伪C++代码,简洁。我想你会明白的 class TCPStream { boost::asio::socket
- TCPStream类:boost asio上的薄包装器
- IPC协议,通过TCP实现协议: 基本上,每条消息都以类型和长度字段开头 因此,我们可以从流中读取单个消息
- 处理消息的连接类
- 监视连接的观察者类
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流{
boost::asio::socket-socket;
公众:
模板
空连接(F)
{
插座连接(f);
}
模板
无效读取(F)
{
插座读数(f);
}
};
IPC类协议:公共TCPStream{
公众:
模板连接();});
读(
[self=shared_from_this()](消息,错误){
如果(!err)
自我->过程(msg);
}否则{
self->error();
}
});
}
空连接()
{
observer.notify_connected(从_this()共享_);
}
无效错误()
{
observer.notify_error(从_this()共享_);
}
};
此模式以这种或那种方式对所有连接重复。
消息由连接类本身处理。但它会让你知道的
其他事件[连接,错误]到观察者。原因-
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);
}
}
}
};
类侦听器{
公众:
虚拟无效通知错误(共享ptr)=0;
虚拟void notify_connect(共享_ptr)=0;
虚空(int类型)=0;
};
类观察员{
std::向量侦听器;
公众:
无效通知连接(共享ptr连接)
{
for(侦听器:侦听器){
如果(侦听器->感兴趣(连接->类型()){
侦听器->通知错误(连接);
}
}
}
};
现在是这个作品的一个粗略的原型。但是我想知道这个课程设计
好的。有多个流式服务器将持续生成状态并将其发送到我的模块,以h/w格式编程状态。这需要扩展,因为将来将添加更多客户端
穿线
遗留代码每个TCP连接有一个线程,这很好。在这里,我试图处理同一线程上的多个连接。仍然会有多个线程调用ioservice。因此,观察器将在多个线程上运行。我计划为每个侦听器设置一个互斥锁,这样侦听器就不会同时获得多个事件。HTTP通过TCP实现一个协议,因此HTTP服务器是您设计的一个良好起点,特别是:
HTTP服务器2
、HTTP服务器3
和HTTP服务器4
注意:连接生存期可能是一个问题,特别是因为您打算将类成员函数用作处理程序,请参见此处的问题和答案:。HTTP通过TCP实现协议,因此HTTP服务器是您设计的良好起点,尤其是:
HTTP服务器2
,HTTP服务器3
和HTTP服务器4
注意:连接生存期可能是一个问题,特别是因为您打算将类成员函数用作处理程序,请参阅此处的问题和答案:。查看HTTP示例确实有帮助。谢谢你的指点。至于生命时间。连接在执行异步操作时为自身提供共享ptr,以使其保持活动状态,直到调用异步完成处理程序为止。你看到这里面有漏洞吗?是的@MGH我确实看到漏洞,特别是:内存和资源泄漏。我希望服务器或客户端拥有共享ptr,并使用“非”成员(或“静态”)函数回调将弱ptr传递给连接。例如,查看连接类。我查看了
类连接。我认为我现在所做的只有几点不同。创建共享指针的静态create
例程。我认为这个想法是为了强制连接总是作为共享指针创建的?(不确定为什么在create()
中使用make_shared
)-好的。但是我的是一个伪代码,用来显示类关系,我跳过了细节。在异步回调中,您为self提供弱ptr,正如我为self提供共享ptr一样。考虑到在任何一种情况下我们都需要关闭套接字,我认为共享ptr是好的,它避免了弱ptr.lock()
==共享指针副本,但我看不到资源泄漏。您可能是对的,弱ptr
不是必需的。但是,它们允许连接类遵循RAII
习惯用法,因此它们是异常安全的。异常可能导致shared\u ptr
s的资源泄漏。查看HTTP示例确实有所帮助。谢谢你的指点。至于生命时间。连接在执行异步操作时为自身提供共享ptr,以使其保持活动状态,直到调用异步完成处理程序为止。你看到这里面有漏洞吗?是的@MGH我确实看到漏洞,特别是:内存和资源泄漏。我希望服务器或客户机拥有共享ptr,并使用“非”成员(或“st”)将弱ptr传递给连接
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);
}
}
}
};