【问题标题】:Finding or building an inter-process broadcast communication channel查找或构建进程间广播通信通道
【发布时间】:2011-06-27 19:02:48
【问题描述】:

所以我们的产品中有这种不寻常的需求。我们在本地主机上运行着许多进程,需要在它们之间构建一种通信方式。困难在于...

  1. 没有“服务器”或主进程
  2. 消息将广播到所有监听节点
  3. 节点都是 Windows 进程,但可能是 C++ 或 C#
  4. 节点将同时在 32 位和 64 位下运行
  5. 任何节点都可以随时跳入/跳出对话
  6. 异常终止的进程不应对其他节点产生不利影响
  7. 响应缓慢的进程也不应该对其他节点产生不利影响
  8. 节点无需“监听”即可广播消息

一些更重要的细节......

我们需要发送的“消息”本质上是微不足道的。消息类型的名称和单个字符串参数就足够了。

通信不一定是安全的,也不需要提供任何身份验证或访问控制手段;但是,我们希望通过 Windows 登录会话对通信进行分组。这里可能有趣的是,非提升的进程应该能够与提升的进程交互,反之亦然。

我的第一个问题:是否有现成的开源库?或者可以用来轻松实现这一目标的东西。到目前为止,我还没有找到任何东西:(

如果不存在用于此的库,那么...您将使用哪些技术来解决此问题?套接字、命名管道、内存映射文件、事件句柄?在完全连接的图中,基于连接的传输(套接字/管道)似乎不是一个好主意,因为 n 个节点需要 n(n-1) 个连接。使用事件句柄和某种形式的共享存储似乎是目前最合理的解决方案……

更新

  • 是否必须可靠且有保证?是的,也不是……假设我在倾听,并且在合理的时间内做出回应,那么我应该总是能收到信息。

  • 典型的邮件大小是多少?少于 100 个字节,包括消息标识符和参数。它们很小。

  • 我们所说的消息速率是多少?低吞吐量是可以接受的,每秒 10 个会很多,平均使用量约为每分钟 1 个。

  • 涉及的进程数是多少?我希望它处理 0 到 50 之间,平均值在 5 到 10 之间。

【问题讨论】:

  • 它必须是可靠和有保证的吗?典型的消息大小是多少?我问的原因是,您可以在环回设备上使用 UDP 端口,并且您要发送的每个“消息”都可以封装在一个数据包中,任何连接到环回端口的进程理论上都应该看到该数据包(如只要你启用了reuseaddr)。

标签: c# .net c++ ipc broadcast


【解决方案1】:

我不知道任何已经存在的东西,但你应该能够通过以下组合构建一些东西:

  • 内存映射文件
  • 活动
  • 互斥体
  • 信号量

这可以以不需要“主”进程的方式构建,因为所有这些都可以创建为命名对象,然后由操作系统管理并且在最后一个客户端使用它们之前不会被销毁。基本思想是启动的第一个进程创建您需要的对象,然后所有其他进程连接到这些对象。如果第一个进程关闭,只要至少有一个其他进程在维护它们的句柄,这些对象就会一直存在。

内存映射文件用于在进程之间共享内存。互斥锁提供同步以防止同时更新。如果您想允许多个读取器或一个写入器,您可以使用一对互斥锁和一个信号量来构建读取器/写入器锁之类的东西(请参阅Is there a global named reader/writer lock?)。并且事件用于在发布新消息时通知所有人。

我已经就一些重要的技术细节挥手致意。例如,知道何时重置事件有点困难。您可以改为让每个应用轮询更新。

但走这条路将提供一种无连接的信息共享方式。它不需要“服务器”进程一直在运行。

对于实现,我建议在 C++ 中实现它,并让 C# 程序通过 P/Invoke 调用它。或者也许在 C# 中,让 C++ 应用程序通过 COM 互操作调用它。当然,这是假设您的 C++ 应用程序是原生的,而不是 C++/CLI。

【讨论】:

【解决方案2】:

我从未尝试过,但理论上它应该可以工作。正如我在评论中提到的,在环回设备上使用 UDP 端口。然后所有进程都可以从/向这个套接字读取和写入。正如你所说,消息很小,所以应该适合每个数据包 - 可能你可以查看谷歌协议缓冲区之类的东西来生成结构,或者只是将结构复制到数据包中发送,然后在另一端进行转换.鉴于这一切都在本地主机上,您无需担心任何对齐、网络顺序类型问题。要支持不同类型的消息,请确保有一个可以检查类型的通用标头,以便向后兼容。

2美分...

【讨论】:

  • 来自 msdn 的注释:“如果 ExclusiveAddressUse 为 false,则多个套接字可以使用 Bind 方法绑定到特定端口;但是只有一个套接字可以对发送到该端口的网络流量执行操作。如果多个套接字尝试使用 Bind(EndPoint) 方法绑定到特定端口,则具有更具体 IP 地址的套接字将处理发送到该端口的网络流量。”我不是套接字专家,但这会起作用吗?这也适用于仅 ipv6 的主机吗?
  • 对不起,单播数据包不会被多个连接接收,第二个选项是使用一个多播组,所有进程都使用相同的端口 - 但至关重要的是,将 TTL 设置为 0 -这将防止数据包泄漏到网络(我认为这应该在 Windows 上工作)
【解决方案3】:

我认为另一个重要的考虑因素是性能,我们在谈论什么消息速率,而不是。进程? 无论哪种方式,您都依赖于允许通信需求的“主”,无论是自定义服务还是提供的系统(管道、消息队列等)。

如果您不需要跟踪和查询过去的消息,我认为您应该考虑一个简单的服务,它打开一个命名管道 - 允许所有其他进程作为 PipeClients 读取或写入它。如果我没记错的话,它会检查您列表中的所有项目。

【讨论】:

  • 此应用程序的部署阻止我们安装服务;但是,DCOM 服务器会像在与用户的会话中启动一样工作。在不可用时打开管道的单个 DCOM 调用听起来是一个值得研究的选项。
【解决方案4】:

您正在寻找的是 Mailslots!

请参阅 CreateMailslot: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365147(v=vs.85).aspx

【讨论】:

  • 不,这将不允许多个进程在同一台机器上从另一个进程接收消息。邮槽广播只能跨网络工作,每个网络节点只能有一个接收器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
相关资源
最近更新 更多