对您的问题的简单或快速回答是:
没关系,尽管除了地图之外,您还可以使用 gb_trees、dict 或 ETS 表(当然,地图是所有这些中最不成熟的)。然而,尽管如此,PID 查找表的键/ID 原则上是可以的。ETS 可能会比其他进程带来性能优势,因为您可以创建一个可以从其他进程访问的 ETS 表,从而消除了单个进程执行所有读取和写入的必要性。这可能重要也可能不重要和/或适当。
一种简单的方法是每次“主机代理”启动时,它都会产生另一个进程,该进程除了链接到“主机代理”之外什么都不做,并从“主机”时从您拥有的任何存储中删除主机 ID 到代理 PID 映射代理”死了。另一种方法是使映射存储进程本身链接到您的主机代理 PID,这可能使您不必担心可能的竞争条件。
可能。当我阅读您的问题时,我留下了某些问题,并且总体感觉我选择的解决方案不会引导我找到您所询问的精确查找问题(即在收到“主机代理”的 PID 时查找TCP 数据包),但我不能确定这不是因为您已经努力将您对 Stack Overflow 的问题最小化。我有点不清楚你的“主机”、“主机代理”和“连接”进程的角色、职责和交互到底是什么,以及它们是否都应该存在和/或有单独的监督树。
因此,寻找可能的替代方案...当您说“当 TCP 数据包到达时”时,我假设您的意思是当外部主机连接到侦听套接字或在已接受的现有套接字上发送一些数据时,并且主机 ID 是主机名(和/或端口)或外部主机在连接后发送给您的其他任意 ID。
无论哪种方式......通常在这种情况下,我希望会产生一个新进程(在你的情况下是“主机代理”)来处理新建立的 TCP 连接(通过动态(例如简单的一对一)主管),取得作为该连接的服务器端端点的套接字的所有权;根据需要读取和写入套接字,并在连接关闭时终止。
使用该模型,如果已经有连接,则应始终启动“主机代理”,如果没有连接,则始终不启动,并且任何传入的 TCP 数据包将自动落入正确的代理手中,因为它将被传递到代理正在处理的套接字,或者如果它是一个新连接,代理将被启动。
现在不再需要在收到 TCP 数据包时查找代理的 PID。
但是,如果您出于其他原因需要查找代理的 PID,因为假设您的服务器有时需要主动向可能连接的“主机”发送数据,那么您要么必须获取所有受监督的“主机代理”的列表并选择正确的(为此,您将使用 supervisor:which_children/1,根据 Hamidreza 的回答)或者您将使用 map、gb_trees、dict、ets 等维护主机 ID 到 PID 的映射。哪个正确取决于关于您可以拥有多少“主机” - 如果它超过少数,那么您可能应该维护某种地图,以便查找时间不会变得太大。
最后的评论,如果你还没有考虑过,你可以考虑看看gproc
,以防你认为它对你的情况有用。它做这种事情。
编辑/添加(以下问题编辑):
您的连接过程对我来说听起来很多余;如上所述,如果您将套接字提供给主机代理,那么连接的大部分责任就消失了。主机代理没有理由无法解析它收到的数据,据我所知,让另一个进程解析它没有任何价值,然后将其传递给另一个进程。解析本身可能是一个确定性函数,因此为它设置一个单独的模块是明智的,但我认为单独的过程没有意义。
我没有看到您的“主机”进程的意义,您说“主机保留主机信息”,这听起来像是一个包含主机名或主机 ID 的进程,诸如此类?
您还说“它指定了源主机和目标主机,这意味着它由源主机发送并应由目标主机接收”这开始使这听起来有点像聊天服务器,或者至少是某种集线器辐条/星号网络风格的通信协议。我不明白为什么你不能通过创建这样的主管树来做你想做的一切:
top_sup
|
.------------------------------.
| | |
map_server svc_listener hosts_sup (simple one to one)
|
.----------------------------->
| | | | | |
在这里,'map_server' 只维护主机 ID 到 PID 的映射hosts
,svc_listener
具有侦听套接字,并且只接受连接并要求在新客户端连接时hosts_sup
产生host
新的连接,并且host
进程(在 下hosts_sup
)负责接受的套接字, 并map_server
在它们启动时注册主机 ID 和它们的 PID 。
如果map_server
链接到host
PID,它可以在死机时自动清理,并且可以为任何进程提供合适的 API 以通过主机 IDhost
查找PID。host