在我的系統中,我有一堆TCP客戶端,我對如何設計它有點困惑[我的大部分經驗都在C中,因此不安全] 。我正在使用boost ASIO來管理連接。這些是分量I具有C++設計:多個TCP客戶端,提升asio和觀察者
- 甲TCPStream類:瘦包裝過大加力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連接,並有一個處理器類 每個連接。讓我們命名它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());
}
};
這種模式重複所有連接的方式或其他。消息由連接類本身處理。但它會讓其他事件[連接,錯誤]知道 給觀察者。究其原因 -
- 重新連接,每次它斷開
- 一羣人需要知道,如果建立連接,使他們能夠 發送初始請求/ confguration到服務器。
- 有些事情,需要根據muliple連接 的連接狀態,例如做:如果連接1和連接2建立,然後開始連接3等
我增加了一箇中間觀測類是存在的,這樣的觀察員每次重新啓動時都必須直接連接到連接。每次連接斷開時,連接類都會被刪除,並創建一個新連接。
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。所以觀察者將在多個線程上運行。我計劃每個Listener都有一個互斥體,以便聽衆不會同時獲得多個事件。
查看HTTP示例確實有幫助。感謝指針。至於生活的時間。 Connection在每次執行異步操作時都會將shared-ptr傳遞給自己,以保持它處於活動狀態,直到調用異步完成處理程序。你有沒有看到這個漏洞? – MGH
是@MGH我確實看到了漏洞,特別是:內存和資源泄漏。我更喜歡服務器或客戶端*擁有* shared-ptr,並使用'non-'member'(或'static')函數回調函數將weak-ptr傳遞給連接。例如,參見連接類[here](https://github.com/kenba/via-httplib/tree/master/include/via/comms)。 – kenba
我看了一下'class Connection'。我只看到與我在做什麼不同的幾點 1.創建共享指針的靜態'create'例程。我認爲這個想法是強制連接始終創建爲共享指針? (不知道爲什麼在'create()'中使用'make_shared') - 沒關係。但我的是一個僞代碼來顯示階級關係,我跳過了細節。 – MGH