Created
November 20, 2012 07:53
-
-
Save frozendevil/4116647 to your computer and use it in GitHub Desktop.
Talking to sockets through dispatch_io_read
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ACAppDelegate.m | |
// SocketTest | |
// | |
// Created by Izzy Fraimow on 11/19/12. | |
// | |
#import "ACAppDelegate.h" | |
#include <arpa/inet.h> | |
@interface ACAppDelegate () | |
@property (nonatomic, assign) BOOL serverStarted; | |
@property (nonatomic, assign) BOOL listening; | |
@property (nonatomic, strong) NSOutputStream *writeSocket; | |
@end | |
@implementation ACAppDelegate | |
// StringFromDispatchData() from Mike Ash's | |
// [Friday Q&A 2011-10-14: What's New in GCD](http://www.mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html) | |
NSString *StringFromDispatchData(dispatch_data_t data) { | |
NSMutableString *s = [NSMutableString stringWithCapacity: dispatch_data_get_size(data)]; | |
dispatch_data_apply(data, ^(dispatch_data_t region, size_t offset, const void *buffer, size_t size) { | |
[s appendFormat: @"%.*s", size, buffer]; | |
return (_Bool)true; | |
}); | |
return s; | |
} | |
static struct sockaddr_in serverAddress; | |
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification; { | |
bzero((char *)&serverAddress, sizeof(serverAddress)); | |
serverAddress.sin_len = sizeof(serverAddress); | |
serverAddress.sin_family = AF_INET; | |
serverAddress.sin_port = htons(2000); | |
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); | |
self.serverStarted = NO; | |
self.listening = NO; | |
} | |
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; { | |
// probably tear down sockets here... or something | |
return NSTerminateNow; | |
} | |
- (IBAction)startListening:(id)sender; { | |
@synchronized(self) { | |
if(!self.serverStarted) { | |
NSLog(@"start the server first, man!"); | |
return; | |
} | |
if(self.listening) { | |
NSLog(@"Bad!"); | |
return; | |
} | |
dispatch_fd_t readSocket = socket(AF_INET, SOCK_STREAM, 0); | |
if (readSocket == -1) { | |
NSLog(@"socket(AF_INET, SOCK_STREAM, 0) failed"); | |
self.listening = NO; | |
return; | |
} | |
if (connect(readSocket, (const struct sockaddr *)&serverAddress, serverAddress.sin_len) == -1) { | |
NSLog(@"Could not connect: %u", errno); | |
self.listening = NO; | |
return; | |
} | |
dispatch_io_t socketChannel = dispatch_io_create(DISPATCH_IO_STREAM, readSocket, dispatch_get_global_queue(0, 0), ^(int error) { | |
if(error) fprintf(stderr, "got an error from stdin: %d (%s)\n", error, strerror(error)); | |
}); | |
dispatch_io_set_low_water(socketChannel, 1); | |
__weak ACAppDelegate *weakSelf = self; | |
dispatch_io_read(socketChannel, 0, SIZE_MAX, dispatch_get_global_queue(0, 0), ^(bool done, dispatch_data_t data, int error) { | |
if(data) { | |
NSString *dataString = StringFromDispatchData(data); | |
NSLog(@"Read data: %@ at time: %@", dataString, [NSDate date]); | |
} | |
if(error) { | |
NSLog(@":("); | |
weakSelf.listening = NO; | |
} | |
if(done) { | |
NSLog(@"Done!"); | |
weakSelf.listening = NO; | |
} | |
}); | |
self.listening = YES; | |
} | |
} | |
- (IBAction)startSocket:(id)sender; { | |
@synchronized(self) { | |
if(self.serverStarted) { | |
NSLog(@"Wtf man?"); | |
return; | |
} | |
dispatch_fd_t writeSocket = socket(AF_INET, SOCK_STREAM, 0); | |
if (writeSocket == -1) { | |
NSLog(@"socket(AF_INET, SOCK_STREAM, 0) failed"); | |
self.serverStarted = NO; | |
return; | |
} | |
bind(writeSocket, (struct sockaddr *) &serverAddress, serverAddress.sin_len); | |
listen(writeSocket, 1024); | |
__weak ACAppDelegate *weakSelf = self; | |
dispatch_async(dispatch_get_global_queue(0, 0), ^{ | |
int connectionSocket; | |
while (1) { | |
if ((connectionSocket = accept(writeSocket, NULL, NULL)) < 0 ) { | |
NSLog(@"ECHOSERV: Error calling accept(): %u", errno); | |
weakSelf.serverStarted = NO; | |
exit(EXIT_FAILURE); | |
} | |
// Uncomment while for NEVER ENDING FUN | |
//while(1 && connectionSocket) { | |
if ( write(connectionSocket, "Hello!", strlen("Hello!")) <= 0 ) { | |
NSLog(@"ECHOSERV: Error calling write(): %u", errno); | |
weakSelf.serverStarted = NO; | |
} | |
sleep(1); | |
//} | |
if ( close(connectionSocket) < 0 ) { | |
NSLog(@"ECHOSERV: Error calling close(): %u", errno); | |
weakSelf.serverStarted = NO; | |
exit(EXIT_FAILURE); | |
} | |
} | |
}); | |
self.serverStarted = YES; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment