Home:ALL Converter>UNIX Domain Sockets and Cocoa

UNIX Domain Sockets and Cocoa

Ask Time:2009-06-13T06:24:41         Author:s4y

Json Formatter

I want to implement IPC in a Cocoa application using UNIX domain sockets, with which I have no experience. I found Apple's CFLocalServer example project, but it's written in C and looks, well, fairly complicated (and yes, I have read most of it).

Are the techniques demonstrated in CFLocalServer still state-of-the-art, or is there a way to implement UNIX domain sockets in Objective-C with Cocoa/Foundation?

I'm playing with NSSocketPorts and NSFileHandles (which provide a healthy amount of abstraction, which is great for this project) and found some very-related code in Mike Bean's Networking in Cocoa, but haven't been able to Make It All Work yet.

Anyone done this before?

Author:s4y,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/989346/unix-domain-sockets-and-cocoa
Arvin :

UNIX Domain Sockets is a tough nut to grab onto. For anyone that has not done so, and is interested then go for it. A sense of accomplishment will ensue afterwards. However, even with the info from Beej and this site or even from Apple there is many disconnects. I am presenting here a conclusive sample for Cocoa that has ARC enabled. I was waiting for Sidnicious and his sample, but never saw anything so I just decided to tackle this myself.\n\nWhat I have here is a header and .m Implementation file with three interfaces.\nA superclass interface and then a server and client interface that inherit.\nI did some limited testing and it seems to work nicely. However, always looking for improvements so please let me know...\n\nHeader File:\n\ntypedef enum _CommSocketServerStatus {\n\n CommSocketServerStatusUnknown = 0,\n CommSocketServerStatusRunning = 1,\n CommSocketServerStatusStopped = 2,\n CommSocketServerStatusStarting = 3,\n CommSocketServerStatusStopping = 4\n\n} CommSocketServerStatus;\n\ntypedef enum _CommSocketClientStatus {\n\n CommSocketClientStatusUnknown = 0,\n CommSocketClientStatusLinked = 1,\n CommSocketClientStatusDisconnected = 2,\n CommSocketClientStatusLinking = 3,\n CommSocketClientStatusDisconnecting = 4\n\n} CommSocketClientStatus;\n\n@class CommSocketServer, CommSocketClient;\n\n@protocol CommSocketServerDelegate <NSObject>\n@optional\n- (void) handleSocketServerStopped:(CommSocketServer *)server;\n- (void) handleSocketServerMsgURL:(NSURL *)aURL fromClient:(CommSocketClient *)client;\n- (void) handleSocketServerMsgString:(NSString *)aString fromClient:(CommSocketClient *)client;\n- (void) handleSocketServerMsgNumber:(NSNumber *)aNumber fromClient:(CommSocketClient *)client;\n- (void) handleSocketServerMsgArray:(NSArray *)aArray fromClient:(CommSocketClient *)client;\n- (void) handleSocketServerMsgDict:(NSDictionary *)aDict fromClient:(CommSocketClient *)client;\n@end\n\n@protocol CommSocketClientDelegate <NSObject>\n@optional\n- (void) handleSocketClientDisconnect:(CommSocketClient *)client;\n- (void) handleSocketClientMsgURL:(NSURL *)aURL client:(CommSocketClient *)client;\n- (void) handleSocketClientMsgString:(NSString *)aString client:(CommSocketClient *)client;\n- (void) handleSocketClientMsgNumber:(NSNumber *)aNumber client:(CommSocketClient *)client;\n- (void) handleSocketClientMsgArray:(NSArray *)aArray client:(CommSocketClient *)client;\n- (void) handleSocketClientMsgDict:(NSDictionary *)aDict client:(CommSocketClient *)client;\n@end\n\n@interface CommSocket : NSObject\n@property (readonly, nonatomic, getter=isSockRefValid) BOOL sockRefValid;\n@property (readonly, nonatomic, getter=isSockConnected) BOOL sockConnected;\n@property (readonly, nonatomic) CFSocketRef sockRef;\n@property (readonly, strong, nonatomic) NSURL *sockURL;\n@property (readonly, strong, nonatomic) NSData *sockAddress;\n@property (readonly, strong, nonatomic) NSString *sockLastError;\n@end\n\n@interface CommSocketServer : CommSocket <CommSocketClientDelegate> { id <CommSocketServerDelegate> delegate; }\n@property (readwrite, strong, nonatomic) id delegate;\n@property (readonly, strong, nonatomic) NSSet *sockClients;\n@property (readonly, nonatomic) CommSocketServerStatus sockStatus;\n@property (readonly, nonatomic) BOOL startServer;\n@property (readonly, nonatomic) BOOL stopServer;\n- (id) initWithSocketURL:(NSURL *)socketURL;\n+ (id) initAndStartServer:(NSURL *)socketURL;\n- (void) addConnectedClient:(CFSocketNativeHandle)handle;\n\n- (void) messageClientsURL:(NSURL *)aURL;\n- (void) messageClientsString:(NSString *)aString;\n- (void) messageClientsNumber:(NSNumber *)aNumber;\n- (void) messageClientsArray:(NSArray *)aArray;\n- (void) messageClientsDict:(NSDictionary *)aDict;\n\n@end\n\n@interface CommSocketClient : CommSocket { id <CommSocketClientDelegate> delegate; }\n@property (readwrite, strong, nonatomic) id delegate;\n@property (readonly, nonatomic) CommSocketClientStatus sockStatus;\n@property (readonly, nonatomic) CFRunLoopSourceRef sockRLSourceRef;\n@property (readonly, nonatomic) BOOL startClient;\n@property (readonly, nonatomic) BOOL stopClient;\n- (id) initWithSocketURL:(NSURL *)socketURL;\n- (id) initWithSocket:(CFSocketNativeHandle)handle;\n+ (id) initAndStartClient:(NSURL *)socketURL;\n+ (id) initWithSocket:(CFSocketNativeHandle)handle;\n\n- (void) messageReceived:(NSData *)data;\n- (BOOL) messageURL:(NSURL *)aURL;\n- (BOOL) messageString:(NSString *)aString;\n- (BOOL) messageNumber:(NSNumber *)aNumber;\n- (BOOL) messageArray:(NSArray *)aArray;\n- (BOOL) messageDict:(NSDictionary *)aDict;\n\n@end\n\n\nImplementation File: (I will present in three sections)\n\nSection I (Superclass)\n\n#import \"CommSocket.h\"\n\n#import <sys/un.h>\n#import <sys/socket.h> \n\n#pragma mark Socket Superclass:\n\n@interface CommSocket ()\n@property (readwrite, nonatomic) CFSocketRef sockRef;\n@property (readwrite, strong, nonatomic) NSURL *sockURL;\n@end\n\n@implementation CommSocket\n@synthesize sockConnected;\n@synthesize sockRef, sockURL;\n\n- (BOOL) isSockRefValid {\n if ( self.sockRef == nil ) return NO;\n return (BOOL)CFSocketIsValid( self.sockRef );\n}\n\n- (NSData *) sockAddress {\n\n struct sockaddr_un address;\n address.sun_family = AF_UNIX;\n strcpy( address.sun_path, [[self.sockURL path] fileSystemRepresentation] );\n address.sun_len = SUN_LEN( &address );\n return [NSData dataWithBytes:&address length:sizeof(struct sockaddr_un)];\n}\n\n- (NSString *) sockLastError {\n return [NSString stringWithFormat:@\"%s (%d)\", strerror( errno ), errno ];\n}\n\n@end\n\n\nSection II (The Server) \n\nNote: The server reuses the Client code for clients that connect to itself.\nOO-programming, gotta love it!\n\n#pragma mark - Socket: Server\n#pragma mark -\n\n@interface CommSocketServer ()\n@property (readonly, nonatomic) BOOL startServerCleanup;\n@property (readwrite, nonatomic) CommSocketServerStatus sockStatus;\n@property (readwrite, strong, nonatomic) NSSet *sockClients;\nstatic void SocketServerCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info);\n@end\n\n#pragma mark - Server Implementation:\n\n@implementation CommSocketServer\n\n@synthesize delegate;\n@synthesize sockStatus;\n@synthesize sockClients;\n\n#pragma mark - Helper Methods:\n\n- (BOOL) socketServerCreate {\n\n if ( self.sockRef != nil ) return NO;\n CFSocketNativeHandle sock = socket( AF_UNIX, SOCK_STREAM, 0 );\n CFSocketContext context = { 0, (__bridge void *)self, nil, nil, nil };\n CFSocketRef refSock = CFSocketCreateWithNative( nil, sock, kCFSocketAcceptCallBack, SocketServerCallback, &context );\n\n if ( refSock == nil ) return NO;\n\n int opt = 1;\n setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));\n setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof(opt));\n\n self.sockRef = refSock;\n CFRelease( refSock );\n\n return YES;\n}\n\n- (BOOL) socketServerBind {\n if ( self.sockRef == nil ) return NO;\n unlink( [[self.sockURL path] fileSystemRepresentation] );\n if ( CFSocketSetAddress(self.sockRef, (__bridge CFDataRef)self.sockAddress) != kCFSocketSuccess ) return NO;\n return YES;\n}\n\n#pragma mark - Connected Clients:\n\n- (void) disconnectClients {\n\n\n for ( CommSocketClient *client in self.sockClients )\n [client stopClient];\n\n self.sockClients = [NSSet set];\n}\n\n- (void) disconnectClient:(CommSocketClient *)client {\n\n @synchronized( self ) {\n NSMutableSet *clients = [NSMutableSet setWithSet:self.sockClients];\n\n if ( [clients containsObject:client] ) {\n\n if ( client.isSockRefValid ) [client stopClient];\n [clients removeObject:client];\n self.sockClients = clients;\n } }\n}\n\n- (void) addConnectedClient:(CFSocketNativeHandle)handle {\n\n @synchronized( self ) {\n CommSocketClient *client = [CommSocketClient initWithSocket:handle];\n client.delegate = self;\n NSMutableSet *clients = [NSMutableSet setWithSet:self.sockClients];\n\n if ( client.isSockConnected ) {\n [clients addObject:client];\n self.sockClients = clients;\n } }\n}\n\n#pragma mark - Connected Client Protocols:\n\n- (void) handleSocketClientDisconnect:(CommSocketClient *)client {\n\n [self disconnectClient:client];\n}\n\n- (void) handleSocketClientMsgURL:(NSURL *)aURL client:(CommSocketClient *)client {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketServerMsgURL:server:fromClient:)] )\n [self.delegate handleSocketServerMsgURL:aURL fromClient:client];\n}\n\n- (void) handleSocketClientMsgString:(NSString *)aString client:(CommSocketClient *)client {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketServerMsgString:fromClient:)] )\n [self.delegate handleSocketServerMsgString:aString fromClient:client];\n}\n\n- (void) handleSocketClientMsgNumber:(NSNumber *)aNumber client:(CommSocketClient *)client {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketServerMsgNumber:fromClient:)] )\n [self.delegate handleSocketClientMsgNumber:aNumber client:client];\n}\n\n- (void) handleSocketClientMsgArray:(NSArray *)aArray client:(CommSocketClient *)client {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketServerMsgArray:fromClient:)] )\n [self.delegate handleSocketServerMsgArray:aArray fromClient:client];\n}\n\n- (void) handleSocketClientMsgDict:(NSDictionary *)aDict client:(CommSocketClient *)client {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketServerMsgDict:fromClient:)] )\n [self.delegate handleSocketServerMsgDict:aDict fromClient:client];\n}\n\n#pragma mark - Connected Client Messaging:\n\n- (void) messageClientsURL:(NSURL *)aURL {\n for ( CommSocketClient *client in self.sockClients)\n [client messageURL:aURL];\n}\n\n- (void) messageClientsString:(NSString *)aString {\n for ( CommSocketClient *client in self.sockClients)\n [client messageString:aString];\n}\n\n- (void) messageClientsNumber:(NSNumber *)aNumber {\n for ( CommSocketClient *client in self.sockClients)\n [client messageNumber:aNumber];\n}\n\n- (void) messageClientsArray:(NSArray *)aArray {\n for ( CommSocketClient *client in self.sockClients)\n [client messageArray:aArray];\n}\n\n- (void) messageClientsDict:(NSDictionary *)aDict {\n for ( CommSocketClient *client in self.sockClients)\n [client messageDict:aDict];\n}\n\n#pragma mark - Start / Stop Server:\n\n- (BOOL) startServerCleanup { [self stopServer]; return NO; }\n\n- (BOOL) startServer {\n\n if ( self.sockStatus == CommSocketServerStatusRunning ) return YES;\n self.sockStatus = CommSocketServerStatusStarting;\n\n if ( ![self socketServerCreate] ) return self.startServerCleanup;\n if ( ![self socketServerBind] ) return self.startServerCleanup;\n\n CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource( kCFAllocatorDefault, self.sockRef, 0 );\n CFRunLoopAddSource( CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes );\n CFRelease( sourceRef );\n\n self.sockStatus = CommSocketServerStatusRunning;\n return YES;\n}\n\n- (BOOL) stopServer {\n\n self.sockStatus = CommSocketServerStatusStopping;\n\n [self disconnectClients];\n\n if ( self.sockRef != nil ) {\n\n CFSocketInvalidate(self.sockRef);\n self.sockRef = nil;\n }\n\n unlink( [[self.sockURL path] fileSystemRepresentation] );\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketServerStopped:)] )\n [self.delegate handleSocketServerStopped:self];\n\n self.sockStatus = CommSocketServerStatusStopped;\n return YES;\n}\n\n#pragma mark - Server Validation:\n\n- (BOOL) isSockConnected {\n\n if ( self.sockStatus == CommSocketServerStatusRunning )\n return self.isSockRefValid;\n\n return NO;\n}\n\n#pragma mark - Initialization:\n\n+ (id) initAndStartServer:(NSURL *)socketURL {\n\n CommSocketServer *server = [[CommSocketServer alloc] initWithSocketURL:socketURL];\n [server startServer];\n return server;\n}\n\n- (id) initWithSocketURL:(NSURL *)socketURL {\n\n if ( (self = [super init]) ) {\n\n self.sockURL = socketURL;\n self.sockStatus = CommSocketServerStatusStopped;\n self.sockClients = [NSSet set];\n\n } return self;\n}\n\n- (void) dealloc { [self stopServer]; }\n\n#pragma mark - Server Callback:\n\nstatic void SocketServerCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {\n\n CommSocketServer *server = (__bridge CommSocketServer *)info;\n\n if ( kCFSocketAcceptCallBack == type ) {\n CFSocketNativeHandle handle = *(CFSocketNativeHandle *)data;\n [server addConnectedClient:handle];\n }\n}\n\n@end\n\n\nSection III (The Client) \n\n#pragma mark - Socket: Client\n#pragma mark -\n\n@interface CommSocketClient ()\n@property (readonly, nonatomic) BOOL startClientCleanup;\n@property (readwrite, nonatomic) CommSocketClientStatus sockStatus;\n@property (readwrite, nonatomic) CFRunLoopSourceRef sockRLSourceRef;\nstatic void SocketClientCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info);\n@end\n\n#pragma mark - Client Implementation:\n\n@implementation CommSocketClient\n\nstatic NSTimeInterval const kCommSocketClientTimeout = 5.0;\n\n@synthesize delegate;\n@synthesize sockStatus;\n@synthesize sockRLSourceRef;\n\n#pragma mark - Helper Methods:\n\n- (BOOL) socketClientCreate:(CFSocketNativeHandle)sock {\n\n if ( self.sockRef != nil ) return NO;\n CFSocketContext context = { 0, (__bridge void *)self, nil, nil, nil };\n CFSocketCallBackType types = kCFSocketDataCallBack;\n CFSocketRef refSock = CFSocketCreateWithNative( nil, sock, types, SocketClientCallback, &context );\n\n if ( refSock == nil ) return NO;\n\n int opt = 1;\n setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof(opt));\n\n self.sockRef = refSock;\n CFRelease( refSock );\n\n return YES;\n}\n\n- (BOOL) socketClientBind {\n if ( self.sockRef == nil ) return NO;\n if ( CFSocketConnectToAddress(self.sockRef, \n (__bridge CFDataRef)self.sockAddress, \n (CFTimeInterval)kCommSocketClientTimeout) != kCFSocketSuccess ) return NO;\n return YES;\n}\n\n#pragma mark - Client Messaging:\n\n- (void) messageReceived:(NSData *)data {\n\n id msg = [NSKeyedUnarchiver unarchiveObjectWithData:data];\n\n if ( [msg isKindOfClass:[NSURL class]] ) {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketClientMsgURL:client:)] )\n [self.delegate handleSocketClientMsgURL:(NSURL *)msg client:self];\n }\n\n else if ( [msg isKindOfClass:[NSString class]] ) {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketClientMsgString:client:)] )\n [self.delegate handleSocketClientMsgString:(NSString *)msg client:self];\n }\n\n else if ( [msg isKindOfClass:[NSNumber class]] ) {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketClientMsgNumber:client:)] )\n [self.delegate handleSocketClientMsgNumber:(NSNumber *)msg client:self];\n }\n\n else if ( [msg isKindOfClass:[NSArray class]] ) {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketClientMsgArray:client:)] )\n [self.delegate handleSocketClientMsgArray:(NSArray *)msg client:self];\n }\n\n else if ( [msg isKindOfClass:[NSDictionary class]] ) {\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketClientMsgDict:client:)] )\n [self.delegate handleSocketClientMsgDict:(NSDictionary *)msg client:self];\n }\n}\n\n- (BOOL) messageData:(NSData *)data {\n\n if ( self.isSockConnected ) {\n\n if ( kCFSocketSuccess == CFSocketSendData(self.sockRef, \n nil, \n (__bridge CFDataRef)data, \n kCommSocketClientTimeout) )\n return YES;\n\n } return NO;\n}\n\n- (BOOL) messageURL:(NSURL *)aURL { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aURL]]; }\n- (BOOL) messageString:(NSString *)aString { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aString]]; }\n- (BOOL) messageNumber:(NSNumber *)aNumber { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aNumber]]; }\n- (BOOL) messageArray:(NSArray *)aArray { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aArray]]; }\n- (BOOL) messageDict:(NSDictionary *)aDict { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aDict]]; }\n\n#pragma mark - Start / Stop Client:\n\n- (BOOL) startClientCleanup { [self stopClient]; return NO; }\n\n- (BOOL) startClient {\n\n if ( self.sockStatus == CommSocketClientStatusLinked ) return YES;\n self.sockStatus = CommSocketClientStatusLinking;\n\n CFSocketNativeHandle sock = socket( AF_UNIX, SOCK_STREAM, 0 );\n if ( ![self socketClientCreate:sock] ) return self.startClientCleanup;\n if ( ![self socketClientBind] ) return self.startClientCleanup;\n\n CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource( kCFAllocatorDefault, self.sockRef, 0 );\n CFRunLoopAddSource( CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes );\n\n self.sockRLSourceRef = sourceRef;\n CFRelease( sourceRef );\n\n self.sockStatus = CommSocketClientStatusLinked;\n return YES;\n}\n\n- (BOOL) stopClient {\n\n self.sockStatus = CommSocketClientStatusDisconnecting;\n\n if ( self.sockRef != nil ) {\n\n if ( self.sockRLSourceRef != nil ) {\n\n CFRunLoopSourceInvalidate( self.sockRLSourceRef );\n self.sockRLSourceRef = nil;\n }\n\n CFSocketInvalidate(self.sockRef);\n self.sockRef = nil;\n }\n\n if ( [self.delegate respondsToSelector:@selector(handleSocketClientDisconnect:)] )\n [self.delegate handleSocketClientDisconnect:self];\n\n self.sockStatus = CommSocketClientStatusDisconnected;\n\n return YES;\n}\n\n#pragma mark - Client Validation:\n\n- (BOOL) isSockConnected {\n\n if ( self.sockStatus == CommSocketClientStatusLinked )\n return self.isSockRefValid;\n\n return NO;\n}\n\n#pragma mark - Initialization:\n\n+ (id) initAndStartClient:(NSURL *)socketURL {\n\n CommSocketClient *client = [[CommSocketClient alloc] initWithSocketURL:socketURL];\n [client startClient];\n return client;\n}\n\n+ (id) initWithSocket:(CFSocketNativeHandle)handle {\n\n CommSocketClient *client = [[CommSocketClient alloc] initWithSocket:handle];\n return client;\n}\n\n- (id) initWithSocketURL:(NSURL *)socketURL {\n\n if ( (self = [super init]) ) {\n\n self.sockURL = socketURL;\n self.sockStatus = CommSocketClientStatusDisconnected;\n\n } return self;\n}\n\n- (id) initWithSocket:(CFSocketNativeHandle)handle {\n\n if ( (self = [super init]) ) {\n\n self.sockStatus = CommSocketClientStatusLinking;\n\n if ( ![self socketClientCreate:handle] ) [self startClientCleanup];\n\n else {\n\n CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource( kCFAllocatorDefault, self.sockRef, 0 );\n CFRunLoopAddSource( CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes );\n\n self.sockRLSourceRef = sourceRef;\n CFRelease( sourceRef );\n\n self.sockStatus = CommSocketClientStatusLinked;\n }\n\n } return self;\n}\n\n- (void) dealloc { [self stopClient]; }\n\n#pragma mark - Client Callback:\n\nstatic void SocketClientCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {\n\n CommSocketClient *client = (__bridge CommSocketClient *)info;\n\n if ( kCFSocketDataCallBack == type ) {\n\n NSData *objData = (__bridge NSData *)data;\n\n if ( [objData length] == 0 )\n [client stopClient];\n\n else\n [client messageReceived:objData];\n }\n}\n\n@end\n\n\nOk, that's it and it should work from different processes. \n\nSimply use this to create a server with the path of where to put the socket file.\n\n\n(id) initAndStartServer:(NSURL *)socketURL;\n\n\nLikewise, use this to create a client connection\n\n\n(id) initAndStartClient:(NSURL *)socketURL;\n\n\nThe rest should be straightforward with the delegate methods I included.\nLastly, keep the url path small (didn't add any real checking for this)\nand you can instantiate these in a separate NSOperationQueue (untested though).\n\nHope this helps someone out there as a complete working sample.\nArvin",
2012-04-30T20:16:07
s4y :

In the end, I did use UNIX domain sockets, and they work pretty well. I have launchd set up the socket for my server (but did write code, successfully, to create it myself), and have the client connect to it.\n\nThings I learned:\n\n\nYou can wrap both ends of the connection in NSFileHandle\nYou do need to use connect() on the client side to create a connection to the socket\nYou should make both the client and the server ignore SIGPIPE\nIf you get called back with zero-length data, it means that the thing on the other end of the socket has disconnected (i.e. the server/client exited). Make sure to close and release your end of the socket in this case — don't try to read data from it again, or just get another zero-length read callback (for ever and ever)\nYou’re responsible for delimiting and assembling the messages you send across the socket (a single message sent on one end may be spit into more than one on the other end, or multiple messages might be merged)\n\n\nI would be happy to share or publish code, just haven’t had the time to clean it up for public consumption. If anyone is interested, let me know.",
2011-08-25T01:00:30
Aiden Bell :

Why not try POSIX named pipes. Mac OSX is a POSIX-ish operating system based on BSD so it should be straight forward:\n\nhttp://www.ecst.csuchico.edu/~beej/guide/ipc/fifos.html",
2009-06-13T01:50:16
yy