How to use NSInputStream and NSOutputStream


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: <a href="https://stackoverflow.com/questions/6685785/stream-to-get-data-nsinputstream" rel="nofollow">this page</a>. 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 NSOutputStreamself.outStream`. Finally, am I doing everything wrong?

Thanks for your answers. Also this is my first question, so any constructive criticism is welcomed.


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; } }


  • Downsampling pcm/wav audio from 22khz to 8khz
  • Convert all images in directory to .mp4 using ffmpeg and a timestamp order
  • IOS Stream Socket
  • Extracting data from 2 tables
  • window event is not working in FireFox
  • Recovering a lost connection using sockets
  • ol.interaction.Select gives an error on ol.source.VectorTile
  • How to annotation order field when using XStream on Android?
  • clearcase rebase permission to specific person
  • How to implement AutoPlay for Windows 7/8
  • Suddenly unable to export to war file from eclipse
  • C# Dictionary ContainsKey
  • How to map childs/parent class with petapoco?
  • Getting push notification payload when user opens app manually after push has been received in the b
  • Change color of row programmatically in WatchKit
  • Linked list in C, no member error
  • Conditional serialization with protobuf-net
  • Ambiguous action methods in MVC 2
  • Can someone explain the exact use of interfaces in C#?
  • Auto Height of UICollectionView inside UITableViewCell
  • Member function pointer cast, from Derived to Base class
  • Is the Go HTTP handler goroutine expected to exit immediately in this case?
  • how to save bool value in KeychainItemWrapper
  • Load 24 bit TGA
  • PHP file_exists() anomaly
  • Generate a unique string based on a pair of strings
  • Deleting a widget from QTableView
  • Unzip archive in .Net CORE 1.0
  • multidatatrigger with multibinding in ControlTemplate.Triggers
  • Streaming screenshots over WebRTC as a video stream from iOS
  • Is there a parser equivalent of 'fragment' marking in ANTLR4?
  • Hide HTML elements without javascript, only CSS
  • Build Successful but not running on simulator
  • Copy to all folders batch file?
  • Play WS (2.2.1): post/put large request
  • Moving mysql files across servers
  • Bad request using file_get_contents for PUT request in PHP
  • How to pass list parameters for each object using Spring MVC?
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • JaxB to read class hierarchy