我有客户端和服务器程序,它们现在通过 TCP 进行通信。我正在尝试使用 POSIX 消息队列(当然,如果客户端和服务器位于同一台计算机上)。我希望它能够提高性能(特别是通过减少延迟)。

我已经解决了大部分问题,但不确定一件事:如何建立“连接”。服务器同时接受来自多个客户端的连接,因此我很想模仿TCP连接建立流程:

  1. 服务器打开一个具有众所周知名称的队列并从中连续读取(它可以使用 select(2) 与 TCP 一样)。
  2. 客户端打开三个队列:两个具有任意名称(包括一些唯一性,例如 PID,以避免冲突),一个具有服务器使用的众所周知的名称。
  3. 客户端向服务器的队列发布一条“连接”消息,包括客户端的队列名称(一个指定用于客户端到服务器的流量,另一个用于相反的情况)。
  4. 服务器打开客户端连接消息中指定的队列,并开始从客户端到服务器的队列中读取(选择)。
  5. 客户端关闭具有众所周知名称的服务器队列。双向通信使用客户端指定的两个队列(每个方向一个)进行。

您可能会发现该方案与常见的 TCP 方法非常相似,这并非偶然。不过,我想知道:

  1. 你能想出更好的方法吗?
  2. 您认为我的方法有任何潜在的问题吗?
  3. 您是否有任何其他想法,包括在同一台计算机上使用消息队列而不是 TCP 实际上会提高性能(延迟)的可能性?

请记住,我以前没有使用过 POSIX 消息队列(我不久前确实使用过 IBM WebSphere MQ,但那是相当不同的)。平台是Linux。

有帮助吗?

解决方案 2

我最终基本上按照我所描述的方式实现了它,并进行了一些增强:

  • 在步骤 2 中,我使用 GUID 作为队列名称,而不是合并客户端的 PID。
  • 在步骤 4 中,我添加了从服务器到客户端发送“接受”消息。
  • 当任何一方希望结束通信时,它会发送“断开连接”消息。

握手比 TCP 更简单,但似乎已经足够了。

至于延迟:好多了。在同一台机器上使用 POSIX 消息队列而不是 TCP 可以减少大约 75% 的延迟。我的消息每条大约 100 字节。

其他提示

  1. 你能想出更好的方法吗?

    也许看看 fifos(又名命名管道)。它们就像网络套接字,但用于本地计算机。它们是单向的,因此您可能需要创建两个,每个方向一个。你的问题确实缺乏任何理由 为什么 您正在专门进行此更改。使用套接字进行进程间通信没有任何问题。它们是双向的、高效的、广泛支持的,并且确实让您可以自由地在以后的机器之间分离进程。

  2. 您认为我的方法有任何潜在的问题吗?

    System V 消息队列和 fifo 命名管道都绝对没问题。Fifo 管道就像常规管道一样,因此您可以通过最少的代码更改进行 read() 和 write()。System V 消息队列需要将数据放入结构中并调用 msgsnd()。然而,任何一种方法都可以。

  3. 您是否有任何其他想法,包括在同一台计算机上使用消息队列而不是 TCP 实际上会提高性能(延迟)的可能性?

    我的其他想法是,正如您所说,您需要开发一种技术,以便每个客户都有一个唯一的标识符。一种方法是将 pid 添加到您传递的结构中,或者在开始时与父级/主控协商一个唯一的 id。另一件需要注意的事情是,System V 消息队列的好处是您可以侦听“选择性”消息,因此您可以理想地使用从服务器到所有客户端的一个队列,每个客户端等待不同的消息。

    我不知道哪种技术可以为您的软件提供最佳吞吐量。确实可能不值得使用 System V 消息队列,但只有您可以做出决定。

菲照明蒂

我比较了 posix MQ 和一对 TCP/IP 套接字的性能。

演示程序有两个线程,一个用于写入,另一个用于读取。

结果是 posix MQ 更快,

  • MQ 460000 tps
  • 套接字对 400000 tps

我遇到了类似的问题,我开发了实时应用程序,需要IPC技术,类似于套接字功能和最小延迟。

您是否将基于POSIX-MQ的解决方案与UNIX本地套接字或TCP套接字进行了比较?

由于

当select()不能对消息队列起作用时,你是如何做到这一点的?什么是Sys V或POSIX? 当PID保证唯一且存储量较小(整数)时,为什么要花费额外的精力来创建GUID到PID查找表?

/ blee /

您还可以在驻留在不同计算机上的程序中使用IPC的消息队列,在这种情况下,您可以使用ZeroMQ( http: //www.zeromq.org )或其他消息队列API,我也建议您考虑它们,并测试它们。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top