|
From: | Marcus Müller |
Subject: | Re: "Modern" server socket programming? |
Date: | Wed, 9 Jan 2013 15:02:04 +0100 |
On 08.01.2013, at 18:45, Richard Frith-Macdonald <address@hidden> wrote: I don't have any demo/example code for a server, but to show it, I chopped out the key bits of a larger program: Just for reference, here is a complete (and tested) example I wrote for my pet project: - (void)setupListenerSocket { self->inputStreams = [NSMutableArray array]; self->serverStream = [GSServerStream serverStreamToAddr:@"" port:0]; NSAssert(self->serverStream, @"Could not open random port?"); [self->serverStream setDelegate:self]; [self->serverStream open]; [self->serverStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } - (void)stream:(NSStream* )_stream handleEvent:(NSStreamEvent)_event { if (_stream == self->serverStream) { switch (_event) { case NSStreamEventHasBytesAvailable: { NSInputStream *is; NSOutputStream *os; [self->serverStream acceptWithInputStream:&is outputStream:&os]; [self->inputStreams addObject:is]; [is setDelegate:self]; [is open]; [is scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; break; } case NSStreamEventNone: case NSStreamEventOpenCompleted: case NSStreamEventHasSpaceAvailable: case NSStreamEventEndEncountered: break; default: NSLog(@"Ignoring event: %ld", _event); break; } } else { NSInputStream *is = (NSInputStream *)_stream; switch (_event) { case NSStreamEventHasBytesAvailable: { NSMutableData *d = [NSMutableData dataWithLength:128]; NSUInteger len = [is read:(uint8_t *)[d bytes] maxLength:[d length]]; if (len > 0) { ((char *)[d bytes])[len + 1] = '\0'; NSString *cmd = [NSString stringWithUTF8String:(const char *)[d bytes]]; NSLog(@"read %ld bytes, string '%@'", len, cmd); } break; } case NSStreamEventEndEncountered: { [self->inputStreams removeObject:is]; break; } case NSStreamEventNone: case NSStreamEventOpenCompleted: case NSStreamEventHasSpaceAvailable: break; default: NSLog(@"Ignoring event: %ld", _event); break; } } } Please note that the actual reading code misses several checks and is pretty naive, but it serves the purpose of demonstrating the mechanism. As a bottom line, I'll have to say that I dislike the structure of the above code. As Richard already said, it's logical to expand the NSStream functionality to server-side as it is done in GNUstep, because it doesn't introduce new API and even the handling doesn't change (you just have to sort out the context the NSStreamEventHasBytesAvailable is currently in as is done above when you have just one object acting as a delegate for everything related to NSStream events). But this dislike is not related to GNUstep, but more to the fact that the -stream:handleEvent: method feels like a C-function, not like a proper method. Personally, I'd prefer separate delegate methods for any relevant event - just as it's modelled in the ULINetSocket class. Another missed opportunity by Apple. ;-) Cheers, Marcus -- Marcus Müller . . . http://www.mulle-kybernetik.com/znek/ |
smime.p7s
Description: S/MIME cryptographic signature
[Prev in Thread] | Current Thread | [Next in Thread] |