如何使用 Objective C 在 OSX 上处理分布式对象?

Vol*_*ike 2 macos cocoa ipc objective-c distributed-objects

截至 2016 年,关于此的Apple 文档已过时且不起作用。例如,他们提到“保留”,但在 XCode 7.1 中默认使用 ARC 并且它不支持“保留”。我在网上尝试了各种示例,但没有一个奏效。我如何在 OSX 上编写称为分布式对象的 IPC 机制,其中客户端应用程序可以调用服务器应用程序上的类方法(就像在 LaunchDaemon 中特别编写的一个,但不是必需的)?

Vol*_*ike 5

这是一个代码示例,可以让您继续前进。server.mm 项目可能最好将它加载到LaunchDaemon 中。我在守护程序以 root 用户身份运行的情况下运行了一些测试,果然以“mike”身份运行的客户端应用程序以“root”身份运行守护程序中的代码。因此,它启用了特权提升。请注意,此 IPC 不提供任何协议加密或身份验证挑战——因此,由您自己添加。您可能会使用 AES256 + Base64 编码加密的密钥/列表、XML 或 JSON 消息以及在发送和接收时使用长而严格的密码短语。请记住,对于特权提升,将一些保护机制落实到位非常重要。

首先启动服务器,它会坐在那里,等待连接。接下来启动客户端,它将建立连接,将数据传递给示例类方法,等待并接收回消息,然后显示并关闭。服务器还将显示已建立的连接以及在发送响应之前在服务器上收到的内容。

请注意,这是一个同步示例,这意味着您调用类方法并等待响应。如果您希望它是异步的,那么您应该阅读有关oneway关键字的 Apple 文档。您将它放在客户端和服务器的类方法声明中。请注意,该oneway关键字实际上仅最好与返回 void 的类方法一起使用,因为您无法在异步类方法上获得响应。因此,您将执行异步调用以启动任务,然后使用同步调用获取您启动的该任务的状态更新。因此,这是一个oneway添加关键字的类方法声明示例:

- (oneway void)runTaskAsync:(NSString *)sParam;
Run Code Online (Sandbox Code Playgroud)

现在,代码...

服务器.m

#import <Foundation/Foundation.h>

#define cat stringByAppendingString

@interface MyService : NSObject {
    NSConnection *connection;
}
@end

@implementation MyService 

- (NSString *)testResponse:(NSString *)s {
    NSLog(@"...connection:%@", s);
    s = [s cat:@"-response"];
    return s;
}

- (void)runService {
    connection = [[NSConnection alloc] init];
    [connection setRootObject:self];
    [connection registerName:@"com.acme.myservice"];
    [[NSRunLoop currentRunLoop] run];
}

@end

int main (int argc, const char *argv[]) {
    @autoreleasepool {
        NSLog(@"ACME MyService 1.0\n");
        MyService *svc = [[MyService alloc] init];
        [svc runService];
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

客户端

#import <Foundation/Foundation.h>

int main (int argc, const char *argv[]) {
    @autoreleasepool {
        NSLog(@"building proxy object");
        id proxy = [NSConnection rootProxyForConnectionWithRegisteredName:@"com.acme.myservice" host:nil];
        NSLog(@"calling test response thru proxy object");
        NSString *sResult = [proxy testResponse:@"sent"];
        NSLog(@"RESULT=%@", sResult);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)