简体   繁体   English

如何在带有Objective C的OSX上分配对象?

[英]How Do I Do Distributed Objects on OSX with Objective C?

As of 2016, the Apple docs on this are stale and don't work. 截至2016年,与此相关的Apple文档已过时,无法正常工作。 For instance, they mention "retain", but in XCode 7.1 the default is to use ARC and it doesn't support "retain". 例如,他们提到“保留”,但是在XCode 7.1中,默认值是使用ARC,并且不支持“保留”。 I tried various examples on the web and none worked. 我在网络上尝试了各种示例,但都无济于事。 How do I code the IPC mechanism called Distributed Objects on OSX, where a client application can call class methods on a server application (like one especially composed in a LaunchDaemon, but not required)? 如何在OSX上编码称为“分布式对象”的IPC机制,在该机制中,客户端应用程序可以在服务器应用程序上调用类方法(例如,特别是在LaunchDaemon中组成的类方法,但不是必需的)?

Here's a code sample to get you going. 这是一个示例代码,助您一臂之力。 The server.mm project is probably best that you load it into a LaunchDaemon . server.mm项目最好是将其加载到LaunchDaemon中 I ran some tests with the daemon running as root user, and sure enough the client application, which was running as "mike", ran the code in the daemon as "root". 我使用守护程序以root用户身份运行了一些测试,并确定足够以“ mike”身份运行的客户端应用程序以“ root”身份运行守护程序中的代码。 So, it enables privilege elevation. 因此,它启用特权提升。 Note that this IPC doesn't provide any protocol encryption or authentication challenges -- so, it's up to you to add that yourself. 请注意,此IPC不会提供任何协议加密或身份验证方面的挑战-因此,您可以自行添加。 You can probably get away with a key/list, XML, or JSON message that's encrypted with AES256 + Base64 encoding with a long, tough password phrase both on sending and receiving. 您可能可以摆脱密钥/列表,XML或JSON消息,该消息使用AES256 + Base64编码进行加密,并在发送和接收时使用长而硬的密码短语。 Remember, with privilege elevation, it's very important that you put some protection mechanisms in place. 请记住,使用特权提升,建立一些保护机制非常重要。

Launch the server first and it will sit there, waiting on connections. 首先启动服务器,它将坐在那里,等待连接。 Launch the client next and it will establish a connection, pass data to a sample class method, wait and receive a message back, and then display it and shut down. 接下来启动客户端,它将建立连接,将数据传递给示例类方法,等待并接收回消息,然后显示并关闭。 The server will also show the connection was made and what was received on the server before a response back was sent. 服务器还将显示已建立连接以及发送回响应之前在服务器上收到的内容。

Note that this is a synchronous example, meaning you call the class method and it waits for a response. 请注意,这是一个同步示例,这意味着您调用类方法,并等待响应。 If you want it to be asynchronous, then you should read the Apple documentation on the oneway keyword . 如果希望它是异步的,则应阅读oneway关键字上的Apple文档。 You put it in both the client and server in the class method declaration. 您将其放在类方法声明中的客户端和服务器中。 Just note that the oneway keyword is really only best used with a class method that returns void because you can't get a response back on an asynchronous class method. 请注意, oneway关键字实际上仅最适合返回void的类方法,因为您无法在异步类方法上获得响应。 So, you'd do an async call to start a task, and then use a synchronous call to get a status update on that task you started. 因此,您将进行异步调用来启动任务,然后使用同步调用来获取启动任务的状态更新。 So, here's an example of a class method declaration that would have the oneway keyword added: 因此,这是一个类方法声明的示例,该示例将添加oneway关键字:

- (oneway void)runTaskAsync:(NSString *)sParam;

And now, the code... 现在,代码...

server.m server.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;
}

client.m client.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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM