截至 2016 年,有关此的Apple 文档已过时且不起作用。例如,他们提到“保留”,但在 XCode 7.1 中默认使用 ARC,它不支持“保留”。我在网上尝试了各种示例,但都没有奏效。如何在 OSX 上编写称为分布式对象的 IPC 机制,其中客户端应用程序可以调用服务器应用程序上的类方法(例如在 LaunchDaemon 中特别组合的方法,但不是必需的)?
1 回答
这是一个代码示例,可以帮助您进行操作。server.mm 项目最好将其加载到LaunchDaemon中。我使用以 root 用户身份运行的守护进程运行了一些测试,果然,以“mike”身份运行的客户端应用程序以“root”身份运行守护进程中的代码。因此,它启用了特权提升。请注意,此 IPC 不提供任何协议加密或身份验证挑战 - 因此,由您自己添加。您可能可以逃脱使用 AES256 + Base64 编码加密的密钥/列表、XML 或 JSON 消息,并在发送和接收时使用长而强硬的密码短语。请记住,对于特权提升,实施一些保护机制非常重要。
首先启动服务器,它会坐在那里等待连接。接下来启动客户端,它将建立连接,将数据传递给示例类方法,等待并接收回消息,然后显示并关闭。服务器还将显示已建立连接以及在发送响应之前在服务器上接收到的内容。
请注意,这是一个同步示例,这意味着您调用类方法并等待响应。如果您希望它是异步的,那么您应该阅读有关oneway
关键字的 Apple 文档。您将它放在类方法声明中的客户端和服务器中。请注意,该oneway
关键字实际上只最好与返回 void 的类方法一起使用,因为您无法在异步类方法上获得响应。因此,您将执行异步调用来启动任务,然后使用同步调用来获取您启动的任务的状态更新。oneway
因此,这是一个添加了关键字的类方法声明的示例:
- (oneway void)runTaskAsync:(NSString *)sParam;
而现在,代码...
服务器.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;
}
客户端.m
#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;
}