Cfmessageport of iOS interprocess communication
iOS systems are name-gated and each app's range of activities is strictly limited to its own sandbox. However, iOS provides a number of interprocess communication mechanisms, and cfmessageport is one of them.
As can be seen from the class name, Cfmessageport belongs to the Core Foundation layer, its implementation is open source, the code can be found in Apple's open source code base.
How to use
1. Message Recipients
The recipient of the Cfmessageport port message needs to implement the following features:
1.1 Register for monitoring
Message receivers need to register for message snooping in the following ways:
-(void) startlistenning{if (0! = Mmsgportlistenner && cfmessageportisvalid (Mmsgportlistenner)) {Cfmes Sageportinvalidate (Mmsgportlistenner); } Mmsgportlistenner = Cfmessageportcreatelocal (Kcfallocatordefault,cfstr (Local_mach_port_name), Onrecvmessagecallback, NULL, NULL); Cfrunloopsourceref Source = Cfmessageportcreaterunloopsource (Kcfallocatordefault, Mmsgportlistenner, 0); Cfrunloopaddsource (Cfrunloopgetcurrent (), source, kcfrunloopcommonmodes); NSLog (@ "Start listenning");}
Where local_mach_port_name is defined as:
#define LOCAL_MACH_PORT_NAME "Com.wangzz.demo"
After viewing the source, Cfmessageport is actually implemented via Mach port. Mach Port is a port-based input source provided by the iOS system and can be used for thread or interprocess communication. The input source types supported by Runloop include port-based input sources, so you can use Runloop as the listener for Cfmessageport port source events.
The above code has several points to explain:
A local Cfmessageportref object can be created by cfmessageportcreatelocal
It is very important that the Cfmessageport object is uniquely identified by a string, where the string is defined by the macro local_mach_port_name;
The Cfmessageport object is created with the callback function Onrecvmessagecallback of the port source event, which is used to handle the port source event;
The created object is added to the runloop as an input source to listen for port source events, and when Runloop receives the corresponding port source event, it invokes the callback method specified in the previous step;
1.2 Implementing Callback Methods
The callback function is the Cfmessageportcallback type, which is defined in part:
typedef cfdataref (*cfmessageportcallback) (Cfmessageportref Local, SInt32 msgid, cfdataref data, void * info);
The meanings of each parameter are:
The Cfmessageportref object that currently receives the message.
This field is useful for identifying messages. If the communication process contract number each msgid corresponding data structure, you can achieve more complex communication.
The real data part of the communication.
The Info field for the Cfmessageportcontext object that is specified when you use the Cfmessageportcreatelocal method to create port ports is usually empty.
This callback method can return a cfdataref type of data to the sender of the port message, which is also important for efficient communication between the two parties.
The implementation of my callback function Onrecvmessagecallback:
Cfdataref onrecvmessagecallback (Cfmessageportref local,sint32 msgid,cfdataref cfdata, void*info) { nslog (@ "onrecvmessagecallback is called"); NSString *strData = nil; if (Cfdata) { const uint8 * recvedmsg = cfdatagetbyteptr (CfData); strdata = [ Nsstring stringwithcstring: (char *) recvedmsg encoding:nsutf8stringencoding]; /** implementing data parsing operations **/ nslog (@ "receive message:%@", Strdata); } //to test, generate return Data NSString *returnString = [NSString stringwithformat:@ "i have receive:%@", Strdata]; const char* cStr = [returnString UTF8String]; NSUInteger ulen = [returnString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; cfdataref sgreturn = cfdatacreate (NULL, (UInt8 *) Cstr, ulen); return sgreturn;}
The method is simple to implement, parsing the agreed data (the contract in the test code is a string), in order to test, and generate a CFDATAREF data returned to the sender of the port message.
1.3 Canceling port snooping
You can unblock port ports in the following ways:
-(void) endlisenning{cfmessageportinvalidate (Mmsgportlistenner); Cfrelease (Mmsgportlistenner);}
Cfmessageportinvalidate stops the send and receive operations for the port message, and only the Cfrelease,cfmessageportref object is called to actually be released.
2. Message sender
Send some code as follows:
-(nsstring *) Sendmessagetodameonwith: (ID) Msginfo msgid: (Nsinteger) msgid{ // Generate remote port cfmessageportref bremote = Cfmessageportcreateremote (Kcfallocatordefault, cfstr (mach_port_remote)); if (nil == bremote) { nslog (@ "bremote create failed"); return nil; } // Build Send data (string) NSString *msg = [nsstring stringwithformat:@ "%@",msginfo]; nslog (@ "send msg is :%@", msg); const char *message = [msg utf8string]; cfdataref data,recvdata = nil; data = cfdatacreate (null, (UInt8 *) message, strlen (message)); // perform the send Operation Cfmessageportsendrequest (Bremote, msgid, data, 0, 100 , kcfrunloopdefaultmode, &recvdata); if (nil == recvData) { nslog (@ "RecvData date is nil. "); cfrelease (data ); Cfmessageportinvalidate (bremote); cfRelease (bremote); return nil; } // Parse return Data Const uint8 * recvedmsg = cfdatagetbyteptr (RecvData); if (nil == recvedmsg) { nslog (@ "Receive date err."); cfrelease (data ); Cfmessageportinvalidate (bremote); cfrelease (bremote); return nil; } nsstring *strmsg = [nsstring stringwithcstring: (Char *) Recvedmsg encoding:nsutf8stringencoding]; nslog (@ " %@ ", STRMSG); cfrelease (data); cfmessageportinvalidate (bremote); cfrelease ( bremote); cfrelease (RecvData); return strmsg;}
Where mach_port_remote is defined as:
#define MACH_PORT_REMOTE "Com.wangzz.demo"
It is relatively simple to send a message, first to generate a remote cfmessageportref through Cfmessageportcreateremote, It is important to note that when Cfmessageportcreateremote is passed, the string uniquely identifies the mach_port_remote must be the same as the string unique to the message recipient when creating the local cfmessageportref.
By looking at the source code discovery, Cfmessageportcreateremote will be based on Mach_port_ The remote defined string is a unique identifier for getting the message receiver to use the same string created by cfmessageportcreatelocal to create the underlying Mach port port, which enables sending information to the message receiver.
If the message receiver has not yet been created or failed to create a local port through cfmessageportcreatelocal, it is definitely a failure to attempt to create the remote port via Cfmessageportcreateremote.
Description
When you create a Cfmessageportref object using Cfmessageportcreatelocal/cfmessageportcreateremote, it will fail, as stated in the official documentation:
This method isn't available on IOS 7 and Later-it would return NULL and log a sandbox violation in syslog. See Concurrency Programming Guide for possible replacement technologies.
Cfmessageport can only be used for local process communication.
Cfmessageport is based on the Mach port communication method, not only can be used for process communication, can also be used for inter-thread communication, but the inter-thread communication with GCD and cocoa provided by the native method, has been very convenient to implement, no need to use Cfmessageport.
Process Communication usage Scenarios
The multi-tasking mechanism of iOS system makes interprocess communication basically only for jailbreak development. The common scenario is that the front end has a UI program for the interface display, and the backend has a Daemo daemon for task processing.
Demo Project
Specifically done a demo project, in order to better demonstrate the use of Cfmessageport, can be downloaded to csdn.
To simulate the interprocess communication scenario, I cfmessageportreceive the message receiving process into a program that can play music in the background so that it can continue to survive after it is cut into the background.
Since Cfmessageport no longer supports iOS7 and later systems, this demo is tested on the IOS6 system.
How to use the demo:
Cfmessageportreceive Start, click Start listenning Create Cfmessageport interface and start listening port message, and then cut cfmessageportreceive to the background;
Start the Cfmessageportsend program, write the content in the input box, and click the Send button to communicate with Cfmessageportreceive.
Messageport There will be log output during the communication process, you can view the log using the following methods:
1. Real Machine
Select: Xcode->window->organizer->devices, and then check the console window of the current device on the left side of the window.
2. Simulator
Select: Open the System log with debug, simulator, or use the shortcut key directly./Open the system console to view the log directly.
Reference documents
Cfmessageport of iOS interprocess communication