我需要一个类Router
来接收IP数据包,将其解析并发送给客户端(来自类Client
)。当然,每个Client
必须告诉Router
他们要接收特定端口的数据包。
template <class T>
class Router
{
public:
//Packets arrive from the world to a Client
virtual bool onReceivePacket(Packet<T>::Ptr packet);
//Packets arrive from a Client to the world
virtual void onSendPacket(Packet<T>::Ptr packet);
protected:
std::unordered_map<int, std::shared_ptr<Client>> tcpRoutingTable;
std::unordered_map<int, std::shared_ptr<Client>> udpRoutingTable;
}
Router
的界面非常简单。有人会用来自世界各地的数据包呼叫onReceivePacket
,而Router
会提取该数据包的目标端口,如果它是TCP或UDP,它将通过在客户端上调用onReceive
相应地路由到客户端。例:auto client = tcpRoutingTable.at(packet->tcpDestination());
client->onReceive(packet);
但是,有两件事困扰着我:
1)如何保持
Router
和Client
之间的关系?如果我只是制作一个Client
并将其订阅到Router
,则Router
还必须在Client
中包含一个指向自身的指针。这种关系非常脆弱,就像Client
或Router
消失一样,它将以不确定的行为结束。同样,通过在shared_ptr
和Client
上简单地使用Router
,我们得到了相互包含且因此永不消失的shared_ptr
递归问题。2)
unordered_map
是路由数据包的最佳方法吗?除了简单地检查整数并将其发送到特定客户端,我认为没有最快的方法。但是,第一个问题的答案米格斯改变了这种模式。如您所见,
Router
是单线程的,因为用来自世界各地的数据包调用Router
的东西也是单线程的。但是我可以受益于多线程吗? 最佳答案
考虑到您对设计目标和限制有更好的了解,以下是技术性答案-您强调简单性。
std :: weak_ptr可用于中断由std :: shared_ptr管理的对象形成的参考周期。
std::weak_ptr
由于您正在考虑并发性,因此请记住以下几点:实现了weak_ptr(Boost库)的前任直接表示,weak_ptr提供的操作子集非常有限,因为在多线程程序中访问其存储的指针通常很危险。您的std实现可能会继承相同的困难-请进行调查或在另一个问题中提问。
在内部,unordered_map中的元素根据其哈希值组织为存储桶,以允许直接通过其键值(平均平均时间复杂度恒定)直接访问各个元素。因此,从性能角度来看,unordered_map的使用很有吸引力。