在Mac OS X上进行进程间通信的最佳方法

32
我计划在Mac上构建一个Cocoa应用程序,其中包括一个后台守护进程(实际上只是一个基本上无界面的Cocoa应用程序),以及0个或多个本地运行的“客户端”应用程序(如果可能的话,我还想支持远程客户端,远程客户端只能是其他Mac或iPhone OS设备)。
要传输的数据将非常简单,主要是文本和命令(可以表示为文本),偶尔可能是一些小文件(例如图像)。
我已经研究了几种方法来完成这个任务,但我不确定哪种方法最适合这个任务。我考虑过以下几点:
  • 读写文件(...是的),非常基本但不太可扩展。
  • 纯Socket(我没有使用Socket的经验,但我认为我可以使用它们在本地和网络上发送数据。尽管在Cocoa中做所有这些似乎很麻烦)
  • Distributed Objects:对于这样的任务似乎相当不优雅
  • NSConnection:我不能真正理解这个类做什么,但我在一些IPC搜索结果中读到了它
我相信还有其他事情我没考虑到,但我很惊讶在这个主题上找不到太多资源。
3个回答

16

我正在研究同样的问题。对我来说,后续可能添加Windows客户端使情况变得更加复杂;在您的情况下,答案似乎更简单。

关于您考虑的选项:

  1. 控制文件:虽然可以通过控制文件进行通信,但必须记住,这些文件需要在涉及的机器之间通过网络文件系统进行通信。因此,网络文件系统充当实际网络基础设施的抽象,但并不提供网络通常具有的全部功能和灵活性。实现:实际上,每对客户端/服务器至少需要两个文件:一个用于服务器向客户端发送请求的文件,以及用于响应的文件。如果每个进程都可以进行双向通信,则需要复制此过程。而且,客户端和服务器都是基于“拉取”的原则运作,即它们需要经常访问控制文件,并查看是否有新内容已传递。

    这种解决方案的优点在于,它最大限度地减少了学习新技术的需求。缺点是它对程序逻辑有很高的要求;你需要注意很多事情(文件是否会被写成一整个部分,还是可能发生任何一方选择不一致的文件?应该实现多频繁的检查?我需要担心文件系统,例如缓存等吗?我能否在不干扰程序代码之外的东西的情况下稍后添加加密?...)

    如果可移植性是一个问题(就我所理解的而言,这不是问题),那么将此解决方案轻松地移植到不同的系统甚至不同的编程语言中将变得很容易。但是,我不知道是否有适用于iPhone OS的任何网络文件系统,但我对此并不熟悉。

  2. 套接字:编程接口肯定是不同的;根据您对套接字编程的经验,可能意味着您需要更多地学习它以及稍后进行调试。实现:实际上,您仍然需要类似于之前的逻辑,即通过网络进行客户端和服务器之间的通信。这种方法的明显优点是,进程可以基于“推送”原则工作,即它们可以侦听套接字,直到收到消息为止,这胜过定期检查控制文件。网络损坏和不一致也不是您要考虑的问题。此外,您(可能)可以更好地控制连接的建立方式,而不是依赖于您的程序所不能控制的事物(如果您决定稍后添加加密,则这一点很重要)。

    优点是许多问题都已经从您的肩膀上解除了,这些问题会困扰实现1。缺点是您仍然需要大幅更改程序逻辑,以确保发送和接收正确的信息(文件类型等)。

    根据我的经验,可移植性(即轻松过渡到不同的系统甚至编程语言)非常好,因为任何与POSIX具有相容性的东西都可以使用。

[编辑: 特别是一旦你传递二进制数字,字节序成为一个问题,你需要手动解决这个问题 - 这是我上面提到的“正确信息”问题的常见特例。例如,当PowerPC与Intel Mac通信时,它会咬你。这个特殊情况消失了,当你使用解决方案3.+4.并解决所有其他“正确信息”的问题时。

  • +4. 分布式对象: 使用NSProxy类集群来实现分布式对象。NSConnection负责建立远程连接,作为发送信息的先决条件,所以一旦你了解如何使用该系统,你也就理解了分布式对象。;^)

    这个想法是,你的高级程序逻辑不需要改变(即,你的对象通过消息进行通信,并接收结果,而消息和返回类型与你从本地实现中习惯的是相同的),而无需担心网络基础结构的细节。好吧,至少在理论上是这样的。 实现:我现在也在研究这个,所以我的理解还很有限。据我所知,你确实需要设置某种结构,即你仍然必须决定哪些进程(本地和/或远程)可以接收哪些消息;这就是NSConnection的作用。在这一点上,你隐式地定义了一个客户端/服务器架构,但你不需要担心2中提到的问题。

    Gnustep项目服务器提供了一个带有两个明确示例的介绍;它说明了技术如何工作,并且是实验的好起点: http://www.gnustep.org/resources/documentation/Developer/Base/ProgrammingManual/manual_7.html

    不幸的是,缺点是完全失去了兼容性(尽管你仍然可以通过你提到的Mac和iPhone/iPad的设置),并且失去了对其他语言的可移植性。使用Objective-C的GNUstep最多只能与代码兼容,但无法在GNUstep和Cocoa之间进行通信,请参见我在这里第2个问题的编辑:CORBA on Mac OS X (Cocoa)

    [编辑: 我刚刚得知另一个信息,我之前不知道。虽然我已经确认了 NSProxy 在 iPhone 上可用,但我没有检查分布式对象机制的其他部分是否可用。根据这个链接:http://www.cocoabuilder.com/archive/cocoa/224358-big-picture-relationships-between-nsconnection-nsinputstream-nsoutputstream-etc.html (在页面上搜索“iPhone OS”这个短语),它们不可用。如果你现在要求使用 iPhone/iPad,则排除此解决方案。

  • 因此,总的来说,学习(实现和调试)新技术的工作量与手动编写低级通信逻辑之间存在权衡。虽然分布式对象方法减轻了大部分负担,并且对程序逻辑的更改最小,但它是最难学习的,也(不幸地)最不可移植。


    @Georg Fritzsche:这可能更多是由于我的学习能力问题,而不是DO的问题;但我过去使用过传统的消息传递系统(MPI)和套接字编程,这可能导致了我在感知上的偏见。我发现很容易弄清楚如何进行数据通信,并且不必担心远程方法调用。DO强制我同时考虑远程方法和数据,这使得这种方法对我来说更加复杂和不直观。 - user8472
    @Evan:在不了解问题和具体情况的情况下,我不会宣传特定的解决方案;不同的问题可能需要不同的解决方案。或者,可以指定在通信时二进制数据必须始终是[小|大]端。还可以使用“XDR”库(外部数据表示)来包装特定类型的数据。我之所以提出这个特定的问题,是因为我以前遇到过这个问题,我也知道其他人在交换二进制数据时不得不解决它。 - user8472
    @GeorgFritzsche 便携式解决方案可能不需要手动编排。例如,XML-RPC具有标准类型映射,如果您拥有良好的XML-RPC框架,则可以为您完成大部分工作。 - khatchad
    此外,还有NSDistributedNotificationCenter,它将NSNotification实现为进程间变体。 - Julian F. Weinert
    对于在同一台机器上的IPC(前台/后台进程),我发现在Windows上使用WM_COPYDATA和NSDistributedNotificationCenter是最好的选择。这只需要一些 #ifdef,实现只有几百行代码。而且速度出奇地快。 - Lothar
    显示剩余5条评论

    14

    免责声明:分布式对象在iPhone上不可用


    你为什么认为分布式对象不太优雅?它们听起来在这里很匹配:

    • 透明地编组基本类型和Objective-C类
    • 客户端是本地的还是远程的并不重要
    • Cocoa应用程序不需要做太多额外的工作

    文档可能会让它看起来比实际更费力,但你基本上只需干净地使用协议并导出,或者连接到服务器的根对象。
    在给定场景中,其余的工作应该会在幕后自动进行。


    3
    这确实是分布式对象设计旨在解决的问题。 - Rob Napier
    1
    @jbr:为什么呢?让别人替你完成工作不是一件好事吗?我认为,链接的文档也很好地解释了机制。 - Georg Fritzsche
    5
    称呼我为守旧派,我总是对那些添加了几层琐碎的“自动化”技术有所怀疑,以便假装远程和本地活动之间没有区别。 (EJB,我在看着你。还有CORBA、DCOM,甚至是老式的RMI。)也许有一天,世界将被包裹在一个单一连续的进程空间中,但在那之前,“这里”不同于“那里”,最好记住这一点。 - walkytalky
    1
    @walkytalky 你有点老派 :)。 - khatchad
    Mac OSX 10.7存在一个bug,当我尝试获取rootProxy时会挂起...但是在10.8中DO运行良好...我尝试建立mach端口并与PrivilagedHelperTool通信... - Orbitus007
    显示剩余4条评论

    7
    我们正在使用 ThoMoNetworking,它运行良好且安装快速。基本上,它允许您在本地网络中发送符合 NSCoding 的对象,但当然也适用于客户端和服务器在同一台机器上的情况。作为基础类的包装器,它负责配对、重新连接等操作。

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