2009-06-12 5 views
5

Ich möchte IPC in einer Cocoa-Anwendung mit UNIX-Domain-Sockets, mit denen ich keine Erfahrung haben, zu implementieren. Ich fand Apples CFLocalServer Beispielprojekt, aber es ist in C geschrieben und sieht gut aus, ziemlich kompliziert (und ja, ich habe das meiste davon gelesen).UNIX Domain Sockets und Cocoa

Sind die in CFLocalServer demonstrierten Techniken immer noch Stand der Technik, oder gibt es eine Möglichkeit, UNIX-Domain-Sockets in Objective-C mit Cocoa/Foundation zu implementieren?

Ich spiele mit NSSocketPort s und NSFileHandle s (was ein gesundes Maß an Abstraktion schaffen, die für dieses Projekt ist groß) und fand einige sehr bezogenen Code in Mike Bean's Networking in Cocoa, haben aber nicht in der Lage gewesen, es alle zu machen Arbeite noch.

Wer hat das schon mal gemacht?

Antwort

4

Am Ende habe ich UNIX-Domain-Sockets verwenden, und sie arbeiten sehr gut. Ich habe launchd den Socket für meinen Server eingerichtet (aber Code erfolgreich geschrieben, um es selbst zu erstellen) und den Client eine Verbindung zu ihm herstellen lassen.

Dinge, die ich gelernt habe:

  • Sie an beiden Enden der Verbindung in NSFileHandle wickeln kann

  • brauchen Sie connect() auf der Clientseite zu verwenden, um eine Verbindung mit dem Sockel

  • zu erstellen
  • Sie sollten sowohl den Client als auch den Server ignorieren SIGPIPE

  • Wenn Wenn Sie mit Daten der Länge null zurückgerufen werden, bedeutet dies, dass die Verbindung am anderen Ende des Sockets getrennt wurde (d. h. der Server/Client wurde beendet). Stellen Sie sicher, Ihr Ende des Sockels in diesem Fall zu schließen und loszulassen - versuchen Sie nicht, Daten von ihm wieder zu lesen, oder rufen Sie einfach einen anderen Null-Länge-Rückruf (für immer und ewig)

  • Sie sind verantwortlich zur Begrenzung und Montag der Nachrichten, die Sie über den Sockel senden (eine einzelne Nachricht an einem Ende gesendet wird, kann in mehr als eine am anderen Ende spucken werden, oder mehrere Nachrichten könnten zusammengefasst werden)

ich würde gerne teilen oder veröffentlichen Code, hatte einfach nicht die Zeit, um es für den öffentlichen Verbrauch aufzuräumen. Wenn jemand interessiert ist, lass es mich wissen.

+0

könnten Sie bitte Ihren Code teilen? –

+0

@ParagBafna Es kann ein paar Tage/Wochen dauern, bis ich es zusammengestellt habe. Mach es so schnell wie möglich. – s4y

+0

Hallo. Ich würde mich für Ihren Code interessieren. Bitte. – Arvin

0

Warum nicht POSIX Named Pipes versuchen. Mac OSX ist ein POSIX-ish Betriebssystem auf BSD basiert, so sollte es einfach sein:

http://www.ecst.csuchico.edu/~beej/guide/ipc/fifos.html

+0

Danke für die Antwort! Soweit ich feststellen kann, haben Named Pipes zwei Enden - und für dieses Projekt brauchte ich eine Ein-Server-Beziehung mit vielen Clients. – s4y

+0

D e d i l n k. –

6

UNIX Domain Sockets Handhabung ist eine harte Nuss auf greifen. Für jeden, der das nicht getan hat und interessiert ist, dann gehen Sie darauf ein. Ein Gefühl der Erfüllung wird danach folgen. Aber selbst mit den Informationen von Beej und dieser Seite oder sogar von Apple gibt es viele Verbindungsunterbrechungen. Ich präsentiere hier ein schlüssiges Beispiel für Cocoa, das ARC aktiviert hat. Ich warte auf Sidnicious und seine Probe, habe aber nie etwas gesehen, also habe ich mich entschieden, das selbst anzugehen.

Was ich hier habe, ist ein Header und .m Implementierungsdatei mit drei Schnittstellen. Eine Superklassenschnittstelle und dann eine Server- und Clientschnittstelle, die erben. Ich habe einige begrenzte Tests durchgeführt und es scheint gut zu funktionieren. Doch immer nach Verbesserungen suchen, so lassen Sie es mich wissen ...

Header-Datei:

typedef enum _CommSocketServerStatus { 

    CommSocketServerStatusUnknown  = 0, 
    CommSocketServerStatusRunning  = 1, 
    CommSocketServerStatusStopped  = 2, 
    CommSocketServerStatusStarting  = 3, 
    CommSocketServerStatusStopping  = 4 

} CommSocketServerStatus; 

typedef enum _CommSocketClientStatus { 

    CommSocketClientStatusUnknown  = 0, 
    CommSocketClientStatusLinked  = 1, 
    CommSocketClientStatusDisconnected = 2, 
    CommSocketClientStatusLinking  = 3, 
    CommSocketClientStatusDisconnecting = 4 

} CommSocketClientStatus; 

@class CommSocketServer, CommSocketClient; 

@protocol CommSocketServerDelegate <NSObject> 
@optional 
- (void) handleSocketServerStopped:(CommSocketServer *)server; 
- (void) handleSocketServerMsgURL:(NSURL *)aURL   fromClient:(CommSocketClient *)client; 
- (void) handleSocketServerMsgString:(NSString *)aString fromClient:(CommSocketClient *)client; 
- (void) handleSocketServerMsgNumber:(NSNumber *)aNumber fromClient:(CommSocketClient *)client; 
- (void) handleSocketServerMsgArray:(NSArray *)aArray fromClient:(CommSocketClient *)client; 
- (void) handleSocketServerMsgDict:(NSDictionary *)aDict fromClient:(CommSocketClient *)client; 
@end 

@protocol CommSocketClientDelegate <NSObject> 
@optional 
- (void) handleSocketClientDisconnect:(CommSocketClient *)client; 
- (void) handleSocketClientMsgURL:(NSURL *)aURL   client:(CommSocketClient *)client; 
- (void) handleSocketClientMsgString:(NSString *)aString client:(CommSocketClient *)client; 
- (void) handleSocketClientMsgNumber:(NSNumber *)aNumber client:(CommSocketClient *)client; 
- (void) handleSocketClientMsgArray:(NSArray *)aArray client:(CommSocketClient *)client; 
- (void) handleSocketClientMsgDict:(NSDictionary *)aDict client:(CommSocketClient *)client; 
@end 

@interface CommSocket : NSObject 
@property (readonly, nonatomic, getter=isSockRefValid) BOOL sockRefValid; 
@property (readonly, nonatomic, getter=isSockConnected) BOOL sockConnected; 
@property (readonly, nonatomic) CFSocketRef sockRef; 
@property (readonly, strong, nonatomic) NSURL *sockURL; 
@property (readonly, strong, nonatomic) NSData *sockAddress; 
@property (readonly, strong, nonatomic) NSString *sockLastError; 
@end 

@interface CommSocketServer : CommSocket <CommSocketClientDelegate> { id <CommSocketServerDelegate> delegate; } 
@property (readwrite, strong, nonatomic) id delegate; 
@property (readonly, strong, nonatomic) NSSet *sockClients; 
@property (readonly, nonatomic) CommSocketServerStatus sockStatus; 
@property (readonly, nonatomic) BOOL startServer; 
@property (readonly, nonatomic) BOOL stopServer; 
- (id) initWithSocketURL:(NSURL *)socketURL; 
+ (id) initAndStartServer:(NSURL *)socketURL; 
- (void) addConnectedClient:(CFSocketNativeHandle)handle; 

- (void) messageClientsURL:(NSURL *)aURL; 
- (void) messageClientsString:(NSString *)aString; 
- (void) messageClientsNumber:(NSNumber *)aNumber; 
- (void) messageClientsArray:(NSArray *)aArray; 
- (void) messageClientsDict:(NSDictionary *)aDict; 

@end 

@interface CommSocketClient : CommSocket { id <CommSocketClientDelegate> delegate; } 
@property (readwrite, strong, nonatomic) id delegate; 
@property (readonly, nonatomic) CommSocketClientStatus sockStatus; 
@property (readonly, nonatomic) CFRunLoopSourceRef sockRLSourceRef; 
@property (readonly, nonatomic) BOOL startClient; 
@property (readonly, nonatomic) BOOL stopClient; 
- (id) initWithSocketURL:(NSURL *)socketURL; 
- (id) initWithSocket:(CFSocketNativeHandle)handle; 
+ (id) initAndStartClient:(NSURL *)socketURL; 
+ (id) initWithSocket:(CFSocketNativeHandle)handle; 

- (void) messageReceived:(NSData *)data; 
- (BOOL) messageURL:(NSURL *)aURL; 
- (BOOL) messageString:(NSString *)aString; 
- (BOOL) messageNumber:(NSNumber *)aNumber; 
- (BOOL) messageArray:(NSArray *)aArray; 
- (BOOL) messageDict:(NSDictionary *)aDict; 

@end 

Implementierungsdatei: (Ich werde in drei Abschnitten wird)

Abschnitt I (Oberklasse)

#import "CommSocket.h" 

#import <sys/un.h> 
#import <sys/socket.h> 

#pragma mark Socket Superclass: 

@interface CommSocket() 
@property (readwrite, nonatomic) CFSocketRef sockRef; 
@property (readwrite, strong, nonatomic) NSURL *sockURL; 
@end 

@implementation CommSocket 
@synthesize sockConnected; 
@synthesize sockRef, sockURL; 

- (BOOL) isSockRefValid { 
    if (self.sockRef == nil) return NO; 
    return (BOOL)CFSocketIsValid(self.sockRef); 
} 

- (NSData *) sockAddress { 

    struct sockaddr_un address; 
    address.sun_family = AF_UNIX; 
    strcpy(address.sun_path, [[self.sockURL path] fileSystemRepresentation]); 
    address.sun_len = SUN_LEN(&address); 
    return [NSData dataWithBytes:&address length:sizeof(struct sockaddr_un)]; 
} 

- (NSString *) sockLastError { 
    return [NSString stringWithFormat:@"%s (%d)", strerror(errno), errno ]; 
} 

@end 

Abschnitt II (Server)

Hinweis: Der Server reus Es ist der Client-Code für Clients, die sich selbst verbinden. OO-Programmierung, ich muss es lieben!

#pragma mark - Socket: Server 
#pragma mark - 

@interface CommSocketServer() 
@property (readonly, nonatomic) BOOL startServerCleanup; 
@property (readwrite, nonatomic) CommSocketServerStatus sockStatus; 
@property (readwrite, strong, nonatomic) NSSet *sockClients; 
static void SocketServerCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info); 
@end 

#pragma mark - Server Implementation: 

@implementation CommSocketServer 

@synthesize delegate; 
@synthesize sockStatus; 
@synthesize sockClients; 

#pragma mark - Helper Methods: 

- (BOOL) socketServerCreate { 

    if (self.sockRef != nil) return NO; 
    CFSocketNativeHandle sock = socket(AF_UNIX, SOCK_STREAM, 0); 
    CFSocketContext context = { 0, (__bridge void *)self, nil, nil, nil }; 
    CFSocketRef refSock = CFSocketCreateWithNative(nil, sock, kCFSocketAcceptCallBack, SocketServerCallback, &context); 

    if (refSock == nil) return NO; 

    int opt = 1; 
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)); 
    setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof(opt)); 

    self.sockRef = refSock; 
    CFRelease(refSock); 

    return YES; 
} 

- (BOOL) socketServerBind { 
    if (self.sockRef == nil) return NO; 
    unlink([[self.sockURL path] fileSystemRepresentation]); 
    if (CFSocketSetAddress(self.sockRef, (__bridge CFDataRef)self.sockAddress) != kCFSocketSuccess) return NO; 
    return YES; 
} 

#pragma mark - Connected Clients: 

- (void) disconnectClients { 


    for (CommSocketClient *client in self.sockClients) 
     [client stopClient]; 

    self.sockClients = [NSSet set]; 
} 

- (void) disconnectClient:(CommSocketClient *)client { 

    @synchronized(self) { 
     NSMutableSet *clients = [NSMutableSet setWithSet:self.sockClients]; 

     if ([clients containsObject:client]) { 

      if (client.isSockRefValid) [client stopClient]; 
      [clients removeObject:client]; 
      self.sockClients = clients; 
    } } 
} 

- (void) addConnectedClient:(CFSocketNativeHandle)handle { 

    @synchronized(self) { 
     CommSocketClient *client = [CommSocketClient initWithSocket:handle]; 
     client.delegate = self; 
     NSMutableSet *clients = [NSMutableSet setWithSet:self.sockClients]; 

     if (client.isSockConnected) { 
      [clients addObject:client]; 
      self.sockClients = clients; 
    } } 
} 

#pragma mark - Connected Client Protocols: 

- (void) handleSocketClientDisconnect:(CommSocketClient *)client { 

    [self disconnectClient:client]; 
} 

- (void) handleSocketClientMsgURL:(NSURL *)aURL client:(CommSocketClient *)client { 

    if ([self.delegate respondsToSelector:@selector(handleSocketServerMsgURL:server:fromClient:)]) 
     [self.delegate handleSocketServerMsgURL:aURL fromClient:client]; 
} 

- (void) handleSocketClientMsgString:(NSString *)aString client:(CommSocketClient *)client { 

    if ([self.delegate respondsToSelector:@selector(handleSocketServerMsgString:fromClient:)]) 
     [self.delegate handleSocketServerMsgString:aString fromClient:client]; 
} 

- (void) handleSocketClientMsgNumber:(NSNumber *)aNumber client:(CommSocketClient *)client { 

    if ([self.delegate respondsToSelector:@selector(handleSocketServerMsgNumber:fromClient:)]) 
     [self.delegate handleSocketClientMsgNumber:aNumber client:client]; 
} 

- (void) handleSocketClientMsgArray:(NSArray *)aArray client:(CommSocketClient *)client { 

    if ([self.delegate respondsToSelector:@selector(handleSocketServerMsgArray:fromClient:)]) 
     [self.delegate handleSocketServerMsgArray:aArray fromClient:client]; 
} 

- (void) handleSocketClientMsgDict:(NSDictionary *)aDict client:(CommSocketClient *)client { 

    if ([self.delegate respondsToSelector:@selector(handleSocketServerMsgDict:fromClient:)]) 
     [self.delegate handleSocketServerMsgDict:aDict fromClient:client]; 
} 

#pragma mark - Connected Client Messaging: 

- (void) messageClientsURL:(NSURL *)aURL { 
    for (CommSocketClient *client in self.sockClients) 
     [client messageURL:aURL]; 
} 

- (void) messageClientsString:(NSString *)aString { 
    for (CommSocketClient *client in self.sockClients) 
     [client messageString:aString]; 
} 

- (void) messageClientsNumber:(NSNumber *)aNumber { 
    for (CommSocketClient *client in self.sockClients) 
     [client messageNumber:aNumber]; 
} 

- (void) messageClientsArray:(NSArray *)aArray { 
    for (CommSocketClient *client in self.sockClients) 
     [client messageArray:aArray]; 
} 

- (void) messageClientsDict:(NSDictionary *)aDict { 
    for (CommSocketClient *client in self.sockClients) 
     [client messageDict:aDict]; 
} 

#pragma mark - Start/Stop Server: 

- (BOOL) startServerCleanup { [self stopServer]; return NO; } 

- (BOOL) startServer { 

    if (self.sockStatus == CommSocketServerStatusRunning) return YES; 
    self.sockStatus = CommSocketServerStatusStarting; 

    if (![self socketServerCreate]) return self.startServerCleanup; 
    if (![self socketServerBind] ) return self.startServerCleanup; 

    CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, self.sockRef, 0); 
    CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); 
    CFRelease(sourceRef); 

    self.sockStatus = CommSocketServerStatusRunning; 
    return YES; 
} 

- (BOOL) stopServer { 

    self.sockStatus = CommSocketServerStatusStopping; 

    [self disconnectClients]; 

    if (self.sockRef != nil) { 

     CFSocketInvalidate(self.sockRef); 
     self.sockRef = nil; 
    } 

    unlink([[self.sockURL path] fileSystemRepresentation]); 

    if ([self.delegate respondsToSelector:@selector(handleSocketServerStopped:)]) 
     [self.delegate handleSocketServerStopped:self]; 

    self.sockStatus = CommSocketServerStatusStopped; 
    return YES; 
} 

#pragma mark - Server Validation: 

- (BOOL) isSockConnected { 

    if (self.sockStatus == CommSocketServerStatusRunning) 
     return self.isSockRefValid; 

    return NO; 
} 

#pragma mark - Initialization: 

+ (id) initAndStartServer:(NSURL *)socketURL { 

    CommSocketServer *server = [[CommSocketServer alloc] initWithSocketURL:socketURL]; 
    [server startServer]; 
    return server; 
} 

- (id) initWithSocketURL:(NSURL *)socketURL { 

    if ((self = [super init])) { 

     self.sockURL  = socketURL; 
     self.sockStatus = CommSocketServerStatusStopped; 
     self.sockClients = [NSSet set]; 

    } return self; 
} 

- (void) dealloc { [self stopServer]; } 

#pragma mark - Server Callback: 

static void SocketServerCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { 

    CommSocketServer *server = (__bridge CommSocketServer *)info; 

    if (kCFSocketAcceptCallBack == type) { 
     CFSocketNativeHandle handle = *(CFSocketNativeHandle *)data; 
     [server addConnectedClient:handle]; 
    } 
} 

@end 

Abschnitt III (Der Kunde)

#pragma mark - Socket: Client 
#pragma mark - 

@interface CommSocketClient() 
@property (readonly, nonatomic) BOOL startClientCleanup; 
@property (readwrite, nonatomic) CommSocketClientStatus sockStatus; 
@property (readwrite, nonatomic) CFRunLoopSourceRef sockRLSourceRef; 
static void SocketClientCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info); 
@end 

#pragma mark - Client Implementation: 

@implementation CommSocketClient 

static NSTimeInterval const kCommSocketClientTimeout = 5.0; 

@synthesize delegate; 
@synthesize sockStatus; 
@synthesize sockRLSourceRef; 

#pragma mark - Helper Methods: 

- (BOOL) socketClientCreate:(CFSocketNativeHandle)sock { 

    if (self.sockRef != nil) return NO; 
    CFSocketContext context = { 0, (__bridge void *)self, nil, nil, nil }; 
    CFSocketCallBackType types = kCFSocketDataCallBack; 
    CFSocketRef refSock = CFSocketCreateWithNative(nil, sock, types, SocketClientCallback, &context); 

    if (refSock == nil) return NO; 

    int opt = 1; 
    setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof(opt)); 

    self.sockRef = refSock; 
    CFRelease(refSock); 

    return YES; 
} 

- (BOOL) socketClientBind { 
    if (self.sockRef == nil) return NO; 
    if (CFSocketConnectToAddress(self.sockRef, 
            (__bridge CFDataRef)self.sockAddress, 
            (CFTimeInterval)kCommSocketClientTimeout) != kCFSocketSuccess) return NO; 
    return YES; 
} 

#pragma mark - Client Messaging: 

- (void) messageReceived:(NSData *)data { 

    id msg = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

    if ([msg isKindOfClass:[NSURL class]]) { 

     if ([self.delegate respondsToSelector:@selector(handleSocketClientMsgURL:client:)]) 
      [self.delegate handleSocketClientMsgURL:(NSURL *)msg client:self]; 
    } 

    else if ([msg isKindOfClass:[NSString class]]) { 

     if ([self.delegate respondsToSelector:@selector(handleSocketClientMsgString:client:)]) 
      [self.delegate handleSocketClientMsgString:(NSString *)msg client:self]; 
    } 

    else if ([msg isKindOfClass:[NSNumber class]]) { 

     if ([self.delegate respondsToSelector:@selector(handleSocketClientMsgNumber:client:)]) 
      [self.delegate handleSocketClientMsgNumber:(NSNumber *)msg client:self]; 
    } 

    else if ([msg isKindOfClass:[NSArray class]]) { 

     if ([self.delegate respondsToSelector:@selector(handleSocketClientMsgArray:client:)]) 
      [self.delegate handleSocketClientMsgArray:(NSArray *)msg client:self]; 
    } 

    else if ([msg isKindOfClass:[NSDictionary class]]) { 

     if ([self.delegate respondsToSelector:@selector(handleSocketClientMsgDict:client:)]) 
      [self.delegate handleSocketClientMsgDict:(NSDictionary *)msg client:self]; 
    } 
} 

- (BOOL) messageData:(NSData *)data { 

    if (self.isSockConnected) { 

     if (kCFSocketSuccess == CFSocketSendData(self.sockRef, 
                nil, 
                (__bridge CFDataRef)data, 
                kCommSocketClientTimeout)) 
      return YES; 

    } return NO; 
} 

- (BOOL) messageURL:(NSURL *)aURL   { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aURL]]; } 
- (BOOL) messageString:(NSString *)aString { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aString]]; } 
- (BOOL) messageNumber:(NSNumber *)aNumber { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aNumber]]; } 
- (BOOL) messageArray:(NSArray *)aArray { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aArray]]; } 
- (BOOL) messageDict:(NSDictionary *)aDict { return [self messageData:[NSKeyedArchiver archivedDataWithRootObject:aDict]]; } 

#pragma mark - Start/Stop Client: 

- (BOOL) startClientCleanup { [self stopClient]; return NO; } 

- (BOOL) startClient { 

    if (self.sockStatus == CommSocketClientStatusLinked) return YES; 
    self.sockStatus = CommSocketClientStatusLinking; 

    CFSocketNativeHandle sock = socket(AF_UNIX, SOCK_STREAM, 0); 
    if (![self socketClientCreate:sock]) return self.startClientCleanup; 
    if (![self socketClientBind]  ) return self.startClientCleanup; 

    CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, self.sockRef, 0); 
    CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); 

    self.sockRLSourceRef = sourceRef; 
    CFRelease(sourceRef); 

    self.sockStatus = CommSocketClientStatusLinked; 
    return YES; 
} 

- (BOOL) stopClient { 

    self.sockStatus = CommSocketClientStatusDisconnecting; 

    if (self.sockRef != nil) { 

     if (self.sockRLSourceRef != nil) { 

      CFRunLoopSourceInvalidate(self.sockRLSourceRef); 
      self.sockRLSourceRef = nil; 
     } 

     CFSocketInvalidate(self.sockRef); 
     self.sockRef = nil; 
    } 

    if ([self.delegate respondsToSelector:@selector(handleSocketClientDisconnect:)]) 
     [self.delegate handleSocketClientDisconnect:self]; 

    self.sockStatus = CommSocketClientStatusDisconnected; 

    return YES; 
} 

#pragma mark - Client Validation: 

- (BOOL) isSockConnected { 

    if (self.sockStatus == CommSocketClientStatusLinked) 
     return self.isSockRefValid; 

    return NO; 
} 

#pragma mark - Initialization: 

+ (id) initAndStartClient:(NSURL *)socketURL { 

    CommSocketClient *client = [[CommSocketClient alloc] initWithSocketURL:socketURL]; 
    [client startClient]; 
    return client; 
} 

+ (id) initWithSocket:(CFSocketNativeHandle)handle { 

    CommSocketClient *client = [[CommSocketClient alloc] initWithSocket:handle]; 
    return client; 
} 

- (id) initWithSocketURL:(NSURL *)socketURL { 

    if ((self = [super init])) { 

     self.sockURL = socketURL; 
     self.sockStatus = CommSocketClientStatusDisconnected; 

    } return self; 
} 

- (id) initWithSocket:(CFSocketNativeHandle)handle { 

    if ((self = [super init])) { 

     self.sockStatus = CommSocketClientStatusLinking; 

     if (![self socketClientCreate:handle]) [self startClientCleanup]; 

     else { 

      CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, self.sockRef, 0); 
      CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); 

      self.sockRLSourceRef = sourceRef; 
      CFRelease(sourceRef); 

      self.sockStatus = CommSocketClientStatusLinked; 
     } 

    } return self; 
} 

- (void) dealloc { [self stopClient]; } 

#pragma mark - Client Callback: 

static void SocketClientCallback (CFSocketRef sock, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { 

    CommSocketClient *client = (__bridge CommSocketClient *)info; 

    if (kCFSocketDataCallBack == type) { 

     NSData *objData = (__bridge NSData *)data; 

     if ([objData length] == 0) 
      [client stopClient]; 

     else 
      [client messageReceived:objData]; 
    } 
} 

@end 

Ok, das ist es, und es sollte aus verschiedenen Prozessen arbeiten.

Verwenden Sie dies einfach, um einen Server mit dem Pfad zu erstellen, wo die Socket-Datei abgelegt werden soll.

  • (id) initAndStartServer: (NSURL *) socketURL;

Ebenso verwenden diese eine Client-Verbindung

  • (id) initAndStartClient zu erstellen: (NSURL *) socketURL;

Der Rest sollte einfach mit den Delegate-Methoden, die ich aufgenommen habe, sein. Schließlich, halten Sie den URL-Pfad klein (keine echte Überprüfung dafür hinzugefügt) und Sie können diese in einer separaten NSOperationQueue instanziieren (nicht getestet, obwohl).

Hoffe das hilft jemand da draußen als eine komplette Arbeitsprobe. Arvin

+0

Super !!! Vielen Dank für diesen sauberen Code. Genau das fehlt in den offiziellen Dokumenten. – codingFriend1

+0

Es sieht so aus, als würde Ihre '-SockAddress' Methode' strcpy() 'über das Ende der Struktur hinausgehen, wenn der Pfad länger als 103 Zeichen ist. Ich vermute, dass die Art und Weise, dies zu beheben, darin besteht, ein großes NSMutableData-Objekt zu erstellen, den Pfad zu kopieren und die Größe der Daten dann auf 'SUN_LEN (& Adresse)' zu ändern. Es ist mir nicht klar, was das 'sun_len'-Feld in diesem Fall sein sollte; Es ist begrenzt durch die Größe eines "unsigned char". –