在 Mac OS X 上进行进程间通信的最佳方式
Posted
技术标签:
【中文标题】在 Mac OS X 上进行进程间通信的最佳方式【英文标题】:Best way to do interprocess communication on Mac OS X 【发布时间】:2010-05-17 02:22:01 【问题描述】:我正在考虑在 Mac 上构建一个带有后端守护进程的 Cocoa 应用程序(实际上可能只是一个大部分无头的 Cocoa 应用程序),以及在本地运行的 0 个或多个“客户端”应用程序(尽管如果可能的话)我也想支持远程客户端;远程客户端只能是其他 Mac 或 iPhone OS 设备。
所传递的数据将是相当微不足道的,主要是文本和命令(我猜无论如何都可以表示为文本),也许偶尔会有小文件(可能是图像)。
我已经查看了一些方法来执行此操作,但我不确定哪种方法最适合手头的任务。我考虑过的事情:
读取和写入文件(……是的),非常基本但不是很可扩展。 纯套接字(我没有使用套接字的经验,但我似乎认为我可以使用它们在本地和通过网络发送数据。虽然如果在 Cocoa 中做所有事情似乎很麻烦 分布式对象:对于这样的任务似乎相当不优雅NSConnection
:我真的不知道这个类是做什么的,但我在一些 IPC 搜索结果中读到了它
我确定我缺少一些东西,但我很惊讶地发现缺乏关于这个主题的资源。
【问题讨论】:
【参考方案1】:我目前正在研究同样的问题。对我来说,以后添加 Windows 客户端的可能性会使情况变得更加复杂。在你的情况下,答案似乎更简单。
关于您考虑过的选项:
控制文件:虽然可以通过控制文件进行通信,但您必须记住,文件需要通过网络文件系统在相关机器之间进行通信。因此,网络文件系统充当实际网络基础设施的抽象,但不提供网络通常具有的全部功能和灵活性。 实现: 实际上,每对客户端/服务器至少需要两个文件:服务器用于向客户端发送请求的文件和用于响应的文件。如果每个进程都可以双向通信,则需要复制它。此外,客户端和服务器都在“拉”的基础上工作,即他们需要经常重新访问控制文件,看看是否有新的东西已经交付。
此解决方案的优势在于它最大限度地减少了学习新技术的需要。最大的缺点是对程序逻辑的要求很高;很多事情需要你处理(文件会写成一个文件,还是会发生任何一方拾取不一致的文件?应该多久执行一次检查?我需要担心文件系统,比如缓存等?我可以稍后添加加密而不玩弄我的程序代码之外的东西吗?...)
如果可移植性是一个问题(据我从您的问题中了解到的情况并非如此),那么此解决方案将很容易移植到不同的系统甚至不同的编程语言。但是,我不知道任何适用于 iPhone OS 的网络文件系统,但我对此并不熟悉。
Sockets:编程接口肯定不一样;根据您对套接字编程的经验,这可能意味着您有更多的工作要先学习它,然后再调试它。 实现:实际上,您将需要与以前类似的逻辑,即客户端和服务器通过网络进行通信。这种方法的一个明确优点是进程可以在“推送”的基础上工作,即它们可以在套接字上侦听直到消息到达,这优于定期检查控制文件。网络损坏和不一致也不是您关心的问题。此外,您(可能)对建立连接的方式拥有更多控制权,而不是依赖程序无法控制的事物(同样,如果您决定稍后添加加密,这很重要)。
优点是您无需承担很多会影响 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,这将排除此解决方案。]
因此,总而言之,一方面是学习(以及实施和调试)新技术的努力,另一方面是手动编码较低级别的通信逻辑。虽然分布式对象方法承担了您的大部分负担,并在程序逻辑中产生了最小的变化,但它是最难学习的,而且(不幸的是)最不便携。
【讨论】:
虽然 DO 确实缺乏可移植性,但我很好奇为什么你觉得它们最难学习?在我看来,可移植的低级解决方案要困难得多,因为您必须自己处理更多层(连接处理、编组......)。 iPhone 上的 DO,遗憾的是它看起来像 you're right。我没注意到,这很烦人。 @Georg Fritzsche:这可能更多是由于我的学习(不)能力而不是 DO;但我过去使用过传统的消息传递系统 (MPI) 和套接字编程,这可能会导致我的感知偏差。我发现很容易弄清楚如何进行数据通信,并且不用担心远程方法调用。 DO 迫使我还考虑除了数据之外的远程方法,这使得这种方法对我来说更加复杂和不直观。 我想,一旦建立连接,通常的面向数据的通信会突然透明地发生,我想可能需要习惯。 :) (旁注:comment notifications 不需要全名) @Georg:一旦涉及到调试,就需要弄清楚一条数据来自哪里以及为什么它看起来像这样。远程和分布式调试绝非易事;不同的语法在这里既无帮助也无害。在 DO 的情况下,多一层抽象和远程方法会引入更多复杂性。也许那些自然而然地思考的人(或者不需要调试她的程序的人;^)不会发现它比面向数据的通信更难,但对我来说它更复杂。【参考方案2】:免责声明:分布式对象是not available on iPhone。
为什么你觉得distributed objects 不优雅?他们在这里听起来很合适:
基本类型和 Objective-C 类的透明编组 客户端是本地还是远程并不重要 对于基于 Cocoa 的应用程序没有太多额外的工作文档听起来可能比实际工作更多,但您基本上要做的就是干净地使用协议并导出或分别连接到服务器根对象。 其余的应该在给定的场景中自动在幕后为您发生。
【讨论】:
+1 这确实是分布式对象旨在解决的问题。 @jbr:为什么,为您完成工作不是一件好事吗?链接的文档也很好地解释了我认为的机制。 我对 DO 的厌恶源于它对异常的广泛使用……感觉不自然。 称我为老式的,但我总是对添加几层精细“自动”以假装远程活动和本地活动之间没有区别的技术有点怀疑。 (EJB,我在看着你。还有 CORBA。还有 DCOM。甚至是 olde worlde RMI。)也许有一天世界会被一个连续的进程空间所包围,但在那之前这里 和 there 不是一回事,记住这一点也不错。 @walkytalky 你太老土了:)。【参考方案3】:我们正在使用ThoMoNetworking,它运行良好且设置速度很快。基本上,它允许您在本地网络中发送符合 NSCoding 的对象,但如果客户端和服务器在同一台机器上,它当然也可以工作。作为基础类的包装器,它负责配对、重新连接等。
【讨论】:
以上是关于在 Mac OS X 上进行进程间通信的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章
C# (.NET 2.0) 中 Windows 的进程间通信