【问题标题】:Using Linux POSIX IPC message queue使用 Linux POSIX IPC 消息队列
【发布时间】:2013-04-16 21:30:04
【问题描述】:

我必须创建单个服务器进程 A 和多个客户端进程。都应该使用 Linux POSIX IPC 消息队列进行数据传递。消息将双向流动。也有可能有时多个客户端进程可能已注册到服务器进程 A。

目前我只使用一个名为消息队列,它由服务器进程 A 创建和打开,并由客户端进程(仅)使用/打开。这适用于两个进程场景(即一个服务器进程 A 和一个客户端进程 B),但不适用于多个客户端进程和一个服务器进程。

我在这里面临的问题是设计/逻辑。我应该如何将服务器进程 A 上的消息从其他客户端进程中解复用,以及从服务器进程 A 的回复应该只发送回各自的客户端进程,或者它可以发送回所有客户端进程,但它必须仅在各自的客户端进程中处理。

例如,我只给出一个场景。 假设进程 A 已创建消息队列 X。进程 B 和 C 现在即将启动并打开消息队列 X。现在进程 B 将请求消息发送到消息队列 X 但这里的问题是进程 A 和进程 C 都将通过入队唤醒事件。在这里,进程 C 如何理解 Message 不属于它。

  • IPC 消息大小小于 128 字节。
  • IPc 消息是定义结构,包含整数和字节数组。结构中没有双/浮点数。
  • IPC 消息队列处于 NON_BLOCKING 模式。
  • 没有关于高性能的要求。
  • 语言:C
  • 编译器:GCC
  • 平台/操作系统:Linux
  • IPC 消息队列:仅 POSIX。
  • 我不打算使用其他 IPC 机制,如 System V 消息或 Unix 本地套接字或管道等。

如果需要更多详细信息,请告诉我。

请建议我解决此问题。

仅供参考:我已经在数据库中搜索过,但我找不到类似的问题已经被问到/回答过,所以请确保在将其标记为重复之前。如果您发现类似的问题已经被询问和回答,请提供链接。

【问题讨论】:

    标签: c linux posix ipc


    【解决方案1】:

    如果我正确理解了场景,那么听起来您将需要多个消息队列。尝试使用单个消息队列在多个进程之间进行双向通信会变成一个复杂的情况。如果没有查看消息的能力,服务器进程甚至很难将特定消息发送到特定客户端。

    • 拥有一个消息队列,它是客户端用来建立“私有”消息队列的通用消息队列。想要打开与服务器的通信通道的客户端可以在此队列上向服务器发送消息。也许让客户端发送队列的名称(例如,可能使用进程 ID)以供服务器打开。
    • 然后服务器可以专门为该客户端打开一个新的消息队列以进行双向通信(或者根据使用情况,打开两个队列可能有意义,一个用于客户端和服务器之间的每个方向)。李>

    【讨论】:

    • 嗨,马克,首先感谢您的即时回复。坦率地说,我有同样的想法(在每个方向都有单独的队列),但我对逻辑的复杂性表示怀疑。你真的认为这只是解决方案还是任何其他替代方案都是可能的?
    • @SujalSheth:假设这是唯一允许的通信机制(我假设是家庭作业),那么是的,我确实认为您需要多个队列。我不认为消息队列支持任何类型的 peek 机制。否则,如果所有人都共享一个队列,那么将特定消息定位到特定进程将非常困难。
    • +1 但我认为最好让客户创建和销毁自己的队列。只需将名称传递给服务器。这可以防止在创建 Q 时出现竞争条件,并且每个客户端都可以处理自己的资源,而不是让服务器这样做变得复杂。
    • @Duck:我也认为在这种情况下会更好。我(可能错误地)从 OP 推断服务器需要创建队列。
    • 我同意 Duck 和 Mark 两个:)
    【解决方案2】:

    也许不是您怀疑的答案,但请考虑完全不使用 POSIX IPC。大约 15 年前,我使用 SysV IPC 设计了一个应用程序。这是我最糟糕的设计决定之一。

    今天我将使用带有适当协议的 TCP/UDP。除了允许将来将单个组件移动到不同的计算机之外,IP 堆栈被大量使用并得到很好的支持。

    使用 TCP,您可以建立良好的 1:1 和单独的 1:many 面向连接的通信。使用 UDP,您可以进行 1:1、1:many 和 many:many 非面向连接的通信。您需要注意安全问题,但有很多有用的教程和支持库。

    对于 TCP/UDP 的可移植性也更好。

    【讨论】:

    • Stocker,由于我的项目限制,我不能使用套接字。让我告诉你更多的信息。在我的项目中,服务器进程代码是我的,但客户端进程代码是别人的。我正在向他们提供我的 API 来与服务器进程通信。我必须在架构完全不同的专有操作系统上工作,所以我已经弄清楚了,并留下了 POSIX IPC 消息队列。顺便说一句,感谢您分享您的经验。
    • 也许下次你有机会影响设计:-)
    • 不过,使用 UDP,您将不得不处理数据包丢失问题。考虑到问题是关于本地 IPC。
    【解决方案3】:

    我在几年前构建了一个像这样的系统,我真的记不住所有细节,但这个想法是在 msgrcv() 中使用一个参数来指示如何从队列中读取消息。

    在消息的类型(msgbuf.type)中,当服务器只想向一个客户端发送消息时,我使用目标进程的 pid 作为消息的类型。客户端只读取类型等于他的 pid 的消息。

    当然,客户端需要在初始化时将他的 pid 发送到服务器。

    【讨论】:

    • msgrcv 是 SysV,OP 需要使用 POSIX MQ。他的困境可以通过 SYSV 的一个队列来解决,但 SysV 更像是一个 PITA,他无论如何都不能使用它。
    【解决方案4】:

    System V 在 msgrcv() 中有一个选项可以从队列中获取特定消息,这样每个客户端都可以读取服务器在单个队列中发布的自己的消息。所以我们可以有一个队列来进行全双工通信.在 POSIX 中没有这样的选项,所以我们必须使用两个单独的队列,一个用于服务器接收来自客户端的所有内容,并且每个客户端都应该有单独的队列来接收 frm 服务器。 qid 应该是全局已知的所有进程。

    【讨论】:

      猜你喜欢
      • 2020-10-30
      • 2019-03-17
      • 2020-11-27
      • 2011-11-04
      • 2012-09-19
      • 2021-03-12
      • 2016-11-26
      • 2014-02-13
      • 2012-08-05
      相关资源
      最近更新 更多