Skip to content

Instantly share code, notes, and snippets.

@frozendevil
Created November 20, 2012 07:53
Show Gist options
  • Save frozendevil/4116647 to your computer and use it in GitHub Desktop.
Save frozendevil/4116647 to your computer and use it in GitHub Desktop.
Talking to sockets through dispatch_io_read
//
// 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