使用POSIX消息队列代替TCP套接字 - 如何建立“连接”?

16
我有客户端和服务器程序,现在通过TCP通信。我正在尝试改用POSIX消息队列(当然是在客户端和服务器在同一台机器上的情况下)。我的希望是它可以提高性能(特别是通过减少延迟)。
大部分都已经解决了,但有一个问题不确定:如何建立"连接"。服务器同时接受来自多个客户端的连接,因此我想仿照TCP连接建立过程实现这样:
1. 服务器使用已知名称打开一个消息队列,并持续从中读取(可以像TCP一样使用select(2))。 2. 客户端打开三个消息队列:两个使用任意名称(包括一些唯一性,例如PID以避免冲突),一个使用服务器使用的已知名称。 3. 客户端向服务器的消息队列发布"连接"消息,包括客户端队列的名称(其中一个被指定为客户端到服务器流量的队列,另一个被指定为相反方向的队列)。 4. 服务器打开客户端连接消息中命名的队列,并开始从客户端到服务器的队列读取(select)。 5. 客户端关闭服务器使用的已知名称的队列。使用客户端指定的两个队列(每个方向一个)进行双向通信。
你可能已经看出这个方案与常见的TCP方法相似,这不是巧合。但我想知道:
1. 你能想到更好的方法吗? 2. 你是否看到我的方法存在潜在问题? 3. 你是否有其他想法,包括使用消息队列而不是TCP在同一台机器上实际上会提高性能(延迟)的可能性?
请记住,我以前没有使用过POSIX消息队列(我曾经使用IBM WebSphere MQ,但那是非常不同的)。平台是Linux。
6个回答

7

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

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

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

至于延迟:它要好得多。在同一台机器上,使用POSIX消息队列而不是TCP,延迟大约降低了75%。我的消息每个大约有100个字节。


7
  1. 你有没有想过更好的方法?

    也许可以看看FIFO(又称命名管道)。它们类似于网络套接字,但是用于本地机器。它们是单向的,因此您可能需要创建两个,一个用于每个方向。您的问题确实缺乏特定更改的原因。使用套接字进行进程间通信没有任何问题。它们是双向的、高效的、广泛支持的,并且确实可以让您在以后将进程分离到不同的机器上。

  2. 你认为我的方法会有什么潜在问题吗?

    System V消息队列和fifo命名管道都非常好。Fifo管道就像普通管道一样,所以您可以使用最少的代码更改进行读取()和写入()。System V消息队列需要将数据放入结构中并调用msgsnd()。这两种方法都可以,但是需要根据具体情况选择。

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

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

    我不知道哪种技术在您的软件中提供最优化的吞吐量。也许使用System V消息队列并不值得,但只有您才能做出决定。

Philluminati


你说我的“问题缺乏改变的原因”。我确实提到了:性能(延迟)。System V消息队列在功能上与POSIX消息队列有什么不同?我正在使用的POSIX消息队列(例如mq_open(3))似乎不支持您提到的“选择性”消息。 - John Zwinck
我现在尝试使用命名管道。它们比POSIX消息队列慢(至少对于传递大量小消息)。 - John Zwinck

3

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

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

结果表明,posix MQ速度更快:

  • MQ 460000 tps
  • socketpair 400000 tps

1

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

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

谢谢


1
我将它们与TCP(当然是在同一台机器上)和命名管道(FIFO)进行了比较。MQ比这两者都要快。我没有比较Unix域套接字,但肯定会对您的结果感兴趣! - John Zwinck

0
当使用消息队列时,如果select()无法工作,您是如何做到的?这是Sys V还是POSIX? 为什么要花费额外的精力创建GUID到PID查找表,当PID保证是唯一的,并且存储更小(整数)?
/blee/

这实际上应该是对我的答案的评论。无论如何: Select确实可以与POSIX消息队列一起使用,这就是我正在使用的。 没有GUID到PID查找表 - GUID在进程之间通信,PID从未被使用。 PIDs不是唯一的 - 在大多数系统上它们会被回收利用。 - John Zwinck

-1

你也可以在不同机器上运行的程序中使用消息队列进行进程间通信,这种情况下你可以使用ZeroMQ(http://www.zeromq.org)或其他消息队列API,我建议你考虑它们,并进行测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接