NSConnection进程间通信ios版

之前逆向Mac上app时,发现有些app会用一个守护进程来和后开启的app来通信,虽然知道是进程间的通信,但是还是不太清楚这是一个怎么样的过程,怎么实现的。今天简单看了一下Mac上的进程间通信是怎么回事。
我看的Mac上用NSConnection来实现进程间通信的。
首先创建NSConnection并设置一个能提供一些协议方法的对象(setRootObject:),有些和http,ftp协议一样的方法。完了之后就注册名字,有点像注册服务一样。然后一个服务端就启动了。
那个么客户端呢?
直接用NSConnection的类方法rootProxyForConnectionWithRegisteredName获取一个NSDistantObject对象。然后设置他要代理的协议(setProtocolForProxy)。那么这个这个对象可以随意调用这些协议。
就这样只要服务端的RootObject实现的协议,客户端都可以去调用。整个过程就像httpFTP等等一些协议一样。
在iOS端呢,虽然你也可以用NSConnection来创建对象。但是却找不到头文件,点进去你会发现它只会在Foundation/NSPort中声名 是一个类


根本用不知道有什么方法来调用,最后我用私有方法获取整个类的声名,写并写进来一个文件,当然包含私有方法:

@interface NSConnection : NSObject

@property (readonly, copy) NSDictionary* statistics;
@property double requestTimeout;
@property double replyTimeout;
@property (retain) id rootObject;
//@property * delegate;
@property BOOL independentConversationQueueing;
@property (readonly, getter=isValid) BOOL valid;
//@property (readonly, retain) id* rootProxy;
@property (readonly, copy) NSArray* requestModes;
@property (readonly, retain) NSPort* sendPort;
@property (readonly, retain) NSPort* receivePort;
@property (readonly) BOOL multipleThreadsEnabled;
@property (readonly, copy) NSArray* remoteObjects;
@property (readonly, copy) NSArray* localObjects;

+ (id) lookUpConnectionWithReceivePort:(id)arg1 sendPort:(id)arg2;
+ (id) connectionWithReceivePort:(id)arg1 sendPort:(id)arg2;
+ (id) connectionWithRegisteredName:(id)arg1 host:(id)arg2 usingNameServer:(id)arg3;
+ (id) serviceConnectionWithName:(id)arg1 rootObject:(id)arg2 usingNameServer:(id)arg3;
+ (id) allConnections;
+ (void) _enableLogging:(BOOL)arg1;
+ (id) connectionWithRegisteredName:(id)arg1 host:(id)arg2;
+ (id) rootProxyForConnectionWithRegisteredName:(id)arg1 host:(id)arg2;
+ (id) rootProxyForConnectionWithRegisteredName:(id)arg1 host:(id)arg2 usingNameServer:(id)arg3;
+ (id) serviceConnectionWithName:(id)arg1 rootObject:(id)arg2;
+ (id) currentConversation;
+ (void) _toggleLogging;
+ (void) initialize;
+ (id) defaultConnection;
+ (id) statistics;

- (void) setRootObject:(id)arg1;
- (id) rootObject;
- (id) receivePort;
- (id) sendPort;
- (void) dispatchWithComponents:(id)arg1;
- (void) handlePortMessage:(id)arg1;
- (void) _portInvalidated:(id)arg1;
- (void) removeRunLoop:(id)arg1;
- (void) returnResult:(id)arg1 exception:(id)arg2 sequence:(unsigned int)arg3 imports:(id)arg4;
- (id) initWithReceivePort:(id)arg1 sendPort:(id)arg2;
- (id) rootProxy;
- (BOOL) registerName:(id)arg1 withNameServer:(id)arg2;
- (void) addRunLoop:(id)arg1;
- (double) replyTimeout;
- (double) requestTimeout;
- (void) _setWhitelist:(id)arg1;
- (void) sendReleasedProxies;
- (id) keyedRootObject;
- (void) addPortsToRunLoop:(id)arg1;
- (void) removePortsFromRunLoop:(id)arg1;
- (void) _encodeProxyList:(id)arg1 forCoder:(id)arg2;
- (void) handleKeyedReleasedProxies:(id)arg1;
- (void) handleUnkeyedReleasedProxies:(char*)arg1 length:(unsigned long)arg2;
- (Class) _portCoderClass;
- (void) _sendBeforeTime:(double)arg1 coder:(id)arg2 doAuthenticationCheck:(BOOL)arg3;
- (BOOL) _verifyComponents:(id)arg1;
- (id) portCoderWithComponents:(id)arg1;
- (void) handlePortCoder:(id)arg1;
- (void) handleRequest:(id)arg1 sequence:(unsigned int)arg2;
- (void) decodeReleasedProxies:(id)arg1;
- (id) newConversation;
- (BOOL) _shouldDispatch:(id*)arg1 invocation:(id)arg2 sequence:(unsigned int)arg3 coder:(id)arg4;
- (id) dispatchInvocation:(id)arg1;
- (void) encodeReleasedProxies:(id)arg1;
- (BOOL) hasRunLoop:(id)arg1;
- (void) sendInvocation:(id)arg1 internal:(BOOL)arg2;
- (void) _authenticateComponents:(id)arg1;
- (BOOL) registerName:(id)arg1;
- (void) setRequestTimeout:(double)arg1;
- (void) setReplyTimeout:(double)arg1;
- (BOOL) independentConversationQueueing;
- (void) setIndependentConversationQueueing:(BOOL)arg1;
- (void) addRequestMode:(id)arg1;
- (void) removeRequestMode:(id)arg1;
- (id) requestModes;
- (id) replyMode;
- (void) setReplyMode:(id)arg1;
- (void) _incrementLocalProxyCount;
- (void) _decrementLocalProxyCount;
- (void) addClassNamed:(char*)arg1 version:(unsigned long)arg2;
- (unsigned long) versionForClassNamed:(id)arg1;
- (void) releaseWireID:(unsigned int)arg1 count:(unsigned long)arg2;
- (id) remoteObjects;
- (id) localObjects;
- (Class) _portCoderClassWithComponents:(id)arg1;
- (BOOL) sendWireCountForWireID:(unsigned int)arg1 port:(id)arg2;
- (void) sendInvocation:(id)arg1;
- (void) _setUseKC:(BOOL)arg1;
- (void) enableMultipleThreads;
- (BOOL) multipleThreadsEnabled;
- (void) runInNewThread;
- (id) retain;
- (oneway void) release;
- (void) dealloc;
- (id) description;
- (void) invalidate;
- (void) setDelegate:(id)arg1;
- (BOOL) isValid;
- (id) delegate;
- (id) init;
- (void) run;
- (id) statistics;

@end

接着你就能像Mac fountion下一样来写进程间的通信了。具体demo会在本文结束时提供地址,包含客户端和服务端。
但是iOS所有App在进入后台时进程会被挂起,这时你可以用一些voip或者下载防止进程被挂起。一旦进程被挂起,客户端就拿不到任何数据了。。
可运行测试的demo:https://github.com/LoveSVN/NSConnectionForios

你可能感兴趣的:(NSConnection进程间通信ios版)