alanı soketlerine ile soket işlemek için iyi bir öğretici üzerine kapmak için zor bir ceviz. Bunu yapmayan ve ilgilenen herkes için bunun peşinden git. Daha sonra bir başarı hissi ortaya çıkacaktır. Ancak, Beej ve bu site veya Apple'dan gelen bilgilerle bile çok fazla bağlantı kesildi. Burada, ARC'nin etkin olduğu Kakao için kesin bir örnek sunuyoruz. Sidnicious ve onun örneğini bekliyordum, ama hiçbir şey görmedim, bu yüzden kendimle baş etmeye karar verdim.
Burada sahip olduğum üç başlıklı bir başlık ve .m Uygulama dosyasıdır. Bir superclass arabirimi ve daha sonra devralan bir sunucu ve istemci arabirimi. Bazı sınırlı testler yaptım ve güzel çalışıyor gibi görünüyor. Ancak, her zaman yenilik arayan yani ... lütfen bana bildirin
Başlık Dosya:
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
Uygulama Dosyası: (Ben üç bölüm halinde sunacak)
Bölüm I (Üst sınıf)
#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
Bölüm II (sunucu)
Not: sunucu reus Kendisine bağlanan istemciler için İstemci kodu. OO programlama, bunu sevmeliyim!
#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
Tamam
#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
Bölüm III (müşteri), o kadar ve farklı işlemler çalışması gerekir.
Bunu yalnızca soket dosyasının nereye yerleştirileceği bir sunucu oluşturmak için kullanın.
- (id) initAndStartServer: (NSURL *) socketURL;
Aynı şekilde, bir istemci bağlantısı
oluşturmak için kullanabilir
- (id) initAndStartClient: (NSURL *) socketURL;
Geri kalan delege yöntemlerini içermelidir. Son olarak, url yolunu küçük tutun (bunun için gerçek bir denetim eklemeyin) ve bunları ayrı bir NSOperationQueue'da (test edilmemiş olsa da) oluşturabilirsiniz.
Bu, çalışan bir örnek olarak dışarıda bir kişi yardımcı olur umarım. Arvin
Kodunuzu paylaşabilir misiniz? –
@ParagBafna Bir araya getirilmeden önce birkaç gün/hafta olabilir. Yapabileceğim en kısa sürede yapar. – s4y
Merhaba. Senin kodunla ilgilenirim. Lütfen. – Arvin