On 08.01.2013, at 18:45, Richard Frith-Macdonald <[email protected]> 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:
>
> PS. using a server socket is exactly like using a client NSStream with the
> exception of two method calls:
> 1. to create the listening stream/socket
> 2. to accept an incoming connection (when the listening socket is readable),
> creating new in/out streams
> This is a direct reflection of the way standard unix/bsd sockets worK, so if
> you know unix socket programming (or cocoa streams programming) it should be
> really easy.
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
_______________________________________________ Gnustep-dev mailing list [email protected] https://lists.gnu.org/mailman/listinfo/gnustep-dev
