问题
I am trying to create a simple multiplayer turn-based game between iPhones. Right now all I want to do is pass in some string to my method, and have the method send the string through the NSOutputStream
. I think I have properly connected my NSNetServices
using NSNetServiceBrowser
. Once they connect, my NSNetServiceDelegate
has netService:didAcceptConnectionWithInputStream:outputStream:
called, which should give me my i/o NSStream pair. My method looks like this:
-(void)netService:(NSNetService *)sender didAcceptConnectionWithInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream{
[self.myNet getInputStream:&inputStream outputStream:&outputStream];
self.inStream = inputStream;
self.outStream = outputStream;
[self.inStream setDelegate:self];
[self.inStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.inStream open];
}
I think I have correctly set up NSInputStream. I also have a delegate for NSStream which is implementing stream:handleEvent:
It looks like this:
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
NSInputStream *inStream = (NSInputStream *)aStream;
BOOL shouldClose = NO;
switch(eventCode) {
case NSStreamEventEndEncountered:
shouldClose = YES;
// If all data hasn't been read, fall through to the "has bytes" event
if(![inStream hasBytesAvailable]) break;
case NSStreamEventHasBytesAvailable: ; // We need a semicolon here before we can declare local variables
uint8_t *buffer;
NSUInteger length;
BOOL freeBuffer = NO;
// The stream has data. Try to get its internal buffer instead of creating one
if(![inStream getBuffer:&buffer length:&length]) {
// The stream couldn't provide its internal buffer. We have to make one ourselves
buffer = malloc(BUFFER_LEN * sizeof(uint8_t));
freeBuffer = YES;
NSInteger result = [inStream read:buffer maxLength:BUFFER_LEN];
if(result < 0) {
// error copying to buffer
break;
}
length = result;
}
// length bytes of data in buffer
if(freeBuffer) free(buffer);
break;
case NSStreamEventErrorOccurred:
// some other error
shouldClose = YES;
break;
case NSStreamEventHasSpaceAvailable:
break;
case NSStreamEventNone:
break;
case NSStreamEventOpenCompleted:
break;
}
if(shouldClose){
[inStream close];
}
}
I took that code from: this page. In that code, aStream
should be self.inStream
. I have looked at pages describing what to do for NSOutputStream
, but none of them seem to be geared at a beginner like me. I have a few questions. Firstly, how do I set up a method that I pass the data in (NSData
or maybe an NSString
) and it sends it out through self.outStream
. I would prefer an answer that explains the code, rather than just giving it to me. Secondly, should I open both of my streams in netService:didAcceptConnectionWithInputStream:outputStream:
, and should I also scheduleInRunLoop
the NSOutputStream
self.outStream`. Finally, am I doing everything wrong?
Thanks for your answers. Also this is my first question, so any constructive criticism is welcomed.
回答1:
To write to output stream, check stream has space available and write data using
- (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)length
So, code may be like following.
if ( self.outStream.hasSpaceAvailable ) [ self.outStream write:... maxLength: ];
If output stream doesn't have space available, later
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
method of the delegate of output stream would be called with eventCode = NSStreamEventHasSpaceAvailable.
You should open output stream and schedule it in netService:didAcceptConnectionWithInputStream:outputStream or when you receive NSStreamEventOpenCompleted of input stream. Both are OK.
If you don't want writing block thread, you need to prepare queue.
So code is like following
NSMutableData* uQueue; NSInputStream* uIStream; NSOutputStream* uOStream; : : : uIStream.delegate = self; uOStream.delegate = self; [ uIStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode ]; [ uOStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode ]; [ uIStream open ]; [ uOStream open ]; uQueue = NSMutableData.data; : : : - (void) Send { if ( uQueue.length ) { NSInteger wLength = [ uOStream write:(const uint8_t*)uQueue.bytes maxLength:uQueue.length ]; if ( wLength > 0 ) [ uQueue replaceBytesInRange:NSMakeRange( 0, wLength ) withBytes:NULL length:0 ]; } } - (void) Write:(NSData*)p { [ uQueue appendData:p ]; if ( uOStream.hasSpaceAvailable ) [ self Send ]; } - (void) stream:(NSStream*)pS handleEvent:(NSStreamEvent)p { switch( p ) { : : : case NSStreamEventHasSpaceAvailable: [ self Send ]; break; } }
来源:https://stackoverflow.com/questions/23186152/how-to-use-nsinputstream-and-nsoutputstream