cocoa - 在 Mac OS X 上进行进程间通信的最佳方式

标签 cocoa networking sockets ipc nsconnection

我正在考虑在 Mac 上构建一个带有后端守护进程的 Cocoa 应用程序(可能实际上只是一个大部分 headless 的 Cocoa 应用程序),以及 0 个或多个在本地运行的“客户端”应用程序(尽管如果可能的话,我会也喜欢支持远程客户端;远程客户端只能是其他 Mac 或 iPhone OS 设备)。

被传达的数据将是相当微不足道的,主要是文本和命令(我想无论如何都可以表示为文本),也许偶尔会有小文件(可能是图像)。

我已经研究了一些这样做的方法,但我不确定哪种方法最适合手头的任务。我考虑过的事情:

  • 读取和写入文件(...是的),非常基本但不是很可扩展。
  • 纯套接字(我没有使用套接字的经验,但我似乎认为我可以使用它们在本地和通过网络发送数据。尽管如果在 Cocoa 中做所有事情似乎很麻烦
  • 分布式对象:对于这样的任务来说似乎相当不雅
  • NSConnection : 我真的不知道这个类到底是做什么的,但我在一些 IPC 搜索结果中读到过它

  • 我确信有些东西是我遗漏的,但我很惊讶地发现缺乏关于这个主题的资源。

    最佳答案

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

    关于您考虑过的选项:

  • 控制文件:虽然可以通过控制文件进行通信,但您必须记住,文件需要通过网络文件系统在所涉及的机器之间进行通信。因此,网络文件系统充当了实际网络基础设施的抽象,但并没有提供网络通常具有的全部功能和灵活性。实现:实际上,每对客户端/服务器至少需要两个文件:服务器用于向客户端发送请求的文件和用于响应的文件。如果每个进程都可以双向通信,则需要重复此操作。此外,客户端和服务器都在“拉”的基础上工作,即他们需要经常重新访问控制文件,看看是否有新的东西已经交付。

    这种解决方案的优点是它最大限度地减少了学习新技术的需要。最大的缺点是对程序逻辑的要求很大;很多事情需要你处理(文件会写成一个还是会发生任何一方捡到不一致的文件?应该多久执行一次检查?我需要担心文件系统吗,像缓存等?我可以稍后添加加密而不用玩弄我的程序代码之外的东西吗?...)

    如果可移植性是一个问题(据我从您的问题中了解到并非如此),那么该解决方案将很容易移植到不同的系统甚至不同的编程语言。但是,我不知道 iPhone 操作系统的任何网络文件系统,但我对此并不熟悉。
  • socket :编程接口(interface)肯定不同;根据您在套接字编程方面的经验,这可能意味着您有更多的工作先学习它,然后再调试它。实现:实际上,您将需要与以前类似的逻辑,即客户端和服务器通过网络进行通信。这种方法的一个明显优点是进程可以在“推送”的基础上工作,即它们可以监听套接字直到消息到达,这优于定期检查控制文件。网络损坏和不一致也不是您关心的问题。此外,您(可能)对建立连接的方式有更多的控制权,而不是依赖于程序控制之外的事情(同样,如果您决定稍后添加加密,这很重要)。

    优点是很多事情都从您的肩膀上卸下来,这些事情会打扰 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,这将排除此解决方案。]

  • 因此,总而言之,一方面学习(以及实现和调试)新技术的努力与另一方面手动编码较低级别的通信逻辑之间存在权衡。虽然分布式对象方法承担了您的大部分负担,并且程序逻辑发生的变化最小,但它是最难学习的,而且(不幸的是)可移植性最差。

    关于cocoa - 在 Mac OS X 上进行进程间通信的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2846337/

    相关文章:

    objective-c - 如何在 NSToolbar 中获取 NSComboBox 以将消息发送到数据源并委托(delegate)

    swift - 根据 NSPopupButton 中的选择更新 NSTextField

    macos - 预加载字体菜单

    java - 从 Socket 获取域名

    java - SocketServer "accept()"方法不起作用?

    iphone - 如何明确地为 CALayer 的背景颜色设置动画?

    java - Android AsyncTask #2 调用 detach()

    iphone - 强制 iPhone 模拟执行 CPU 密集型任务?

    java - 使用 servlet 的套接字服务器

    javascript - 是否可以在 node.js 服务器上设置运行(服务器端)的 socket.io 客户端?