使用POSIX消息队列或Unix域套接字进行本地IPC通信是否更好?
我在机器之间使用了Unix套接字(不是域名),我记得在最终离开之前,建立和断开连接会导致套接字停留一段时间。此外,如果您想要“可靠”的交换,您必须使用TCP或设计应用程序以返回ACK。我不确定这是否也适用于Unix域套接字。
在我目前的项目中,我们需要本地IPC。我的第一反应是使用POSIX MQueues,因为我之前使用它们进行本地消息传递。但是,一位同事正在建议使用Unix域套接字。
一个人比另一个好,还是编程熟悉?或者它可能取决于正在创建的应用程序?
总体而言,我们正在开发的应用程序遵循客户端/服务器模型。客户端向服务器发送消息以“做某事”。但是,客户端不会等待“完成”响应 - 尽管他们确实想知道他们的请求是否已收到。
发送方的基本逻辑是:
connect to server
send request
note if the send worked or not
disconnect from server
一台服务器可能有数百个客户端。
我们正在运行Linux操作系统的SMP系统(4-8核)上执行。
提前致谢。
答案 0 :(得分:5)
UNIX域套接字不必像TIME_WAIT
那样“延迟”状态,因为如果来自连接的杂散数据包仍然在Internet上闲逛,则使用该等待时间。这种担忧并不适用于当地。
UNIX域套接字可以是SOCK_STREAM
(如TCP)或SOCK_DGRAM
(如UDP),还可以保证UNIX域数据报套接字是可靠的,不会重新排序数据报。 / p>
如果您希望某些您的其他应用程序已阅读您发送的消息,您仍需要某种ACK(甚至使用TCP);毕竟,即使send()
成功,它也可能在它有机会处理消息之前崩溃了。 (这也适用于消息队列 - 完全确定消息不会丢失,接收应用程序必须将请求写入日志,将其刷新到磁盘然后发回确认)。
我同意这个选择基本上是编程熟悉的问题。
答案 1 :(得分:4)
一个人比另一个好,还是编程熟悉?或者它可能取决于正在创建的应用程序?
与UNIX域数据报套接字相比,SysV消息队列具有我所知的主要差异:
您可以poll()
套接字,但不能发送消息队列。
消息队列是全局的,并且可能(并且通常会)需要一些管理参与:清除旧的SysV资源是许多系统管理员日常例程之一。虽然UNIX域的语义要简单得多,但应用程序通常可以在没有系统管理员参与的情况下完全内部维护它。
(?)消息队列是持久的,它可能会保留旧会话的消息。 (不能回忆起那一点,但是IIRC不止一次发生在我身上)。
查看man msgrcv
我看不到套接字MSG_PEEK
的模拟内容。很少需要,但有时候非常方便。
大多数情况下,用户更喜欢使用配置符号名称,而不是数字键ID。缺乏符号键IMO对部分SysV界面设计师非常严格疏忽。
与所有SysV资源一样,他们的管理是主要的PITA。如果让系统决定消息队列ID,那么您必须正确地与其他应用程序共享它。 (而且你还必须以某种方式告诉管理员最终必须删除ID)。如果您允许为消息队列配置密钥,那么您可能会遇到一些微不足道的问题,即某个应用程序已经使用了该ID,或者它是上一次运行的剩余部分。 (仅仅因为SysV资源耗尽而导致服务器重启是非常常见的。)
总而言之,我尽可能避免使用SysV资源:在最常见的情况下缺乏poll()
支持是一种交易破坏。
但是,客户端不会等待“完成”响应 - 尽管他们确实想知道他们的请求是否已收到。
这是交易处理的常见困境。一般响应(如在RDBMS中)您不能并且在通信中断(崩溃或其他)之后,应用程序必须检查自己是否已经处理了请求。
从中可以看出,TCP可能是更好的选择。客户端发送请求并仅在从服务器获得肯定响应时将其声明为已完成。服务器除非能够将响应发送给客户端,否则必须回滚事务。
答案 2 :(得分:3)
我建议将DBus用于这样的应用程序,如果仅用于数据编组和类似RPC的接口(同步和异步)。它本地使用域套接字,并且在初始学习曲线之后工作得非常好。