PDA

View Full Version : NSStream Send & Receive Handler


jasonjohnson
2005.09.28, 12:11 PM
Not being at all new to network programming, the concepts behind socket-level communication between hosts is familiar to me. The technical execution of this using NSStream, however, is a little fuzzy.

I am very interested in networked game-play, and am simply trying to understand the fundamentals of building this sort of thing using Cocoa and Objective-C.

The following is what I have pulled together out of some intensely complicated applications. It appears to do a little something, throwing off no errors and launching quickly and without fault.

How is it I modify this code to handle the actual acceptance of data? Are there any exceedingly simple examples I could reference? Any tips for organizing this kind of functionality? Am I completely lost and unaware of it? :)


- (IBAction)doSend:(id)sender
{
NSString * strHost = @"www.idevgames.com";
NSHost * objHost = [NSHost hostWithName:strHost];
int intPort = 80;
uint8_t buffer[1024];

[NSStream getStreamsToHost:objHost
port:intPort
inputStream:&receiveStream
outputStream:&sendStream];

[receiveStream retain];
[sendStream retain];

[receiveStream close];
[sendStream close];
}


Thanks!

Taxxodium
2005.09.28, 01:40 PM
Have you read this (http://developer.apple.com/documentation/Cocoa/Conceptual/Streams/index.html)?

jasonjohnson
2005.09.28, 03:30 PM
No, I have not read this -- though I will certainly do so now. I had been working off the documentation for the specific classes involved: NSStream (http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSStream.html), NSInputStream (http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSInputStream.html#//apple_ref/doc/uid/20001982), and NSOutputStream (http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSOutputStream.html#//apple_ref/doc/uid/20001983). I was not aware a conceptual overview existed.

When I am finished reading and have a working implementation of these classes, I will make sure and post the code for further scrutiny.

I certainly appreciate the link. Hopefully this will prove to be what I've been looking for. :)

jasonjohnson
2005.09.29, 12:14 PM
Nearly there. The article did help explain a few things. However, now that I have stream events firing properly, I'm looking for a more elegant way to write and read to and from the streams.

The "open" and "close" methods are tied to interface elements through a simple controller, and the stream event handler (like I mentioned above) seems to be doing its job very well. On each event, it's printing to the console.

Following the NSStreamEventOpenCompleted event of "sendStream", I attempted to write the beginnings of an HTTP request (per the example in the article), and yet when doing so, a socket error occurs and the request seems to be lost.

My question isn't regarding the troubleshooting of this particular issue - but rather - surely there is a simpler way to write to an open stream? Anyone have any suggestions? For that matter, is there an equally slick way to read from streams?

Mostly a style issue, but I just don't like how nasty this code could get.

Just FYI: I fully plan to develop two new methods for reading and writing, but for the moment, I am simply trying to get this to work. I do not want to introduce too much overhead and room for error during this exercise. I know the placement of this particular write to the sream is a little wonky :p


#import "Connection.h"

@implementation Connection

-(void) open: (NSString *) h : (int) p
{
strHost = h;
intPort = p;

[NSStream getStreamsToHost:objHost
port:intPort
inputStream:&receiveStream
outputStream:&sendStream];

[receiveStream retain];
[sendStream retain];

[receiveStream setDelegate:self];
[sendStream setDelegate:self];

[receiveStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[sendStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

[receiveStream open];
[sendStream open];

printf("Open.\n");
}


- (void) stream: (NSStream *) stream handleEvent: (NSStreamEvent) eventCode
{
printf("EVENT: Start.\n");

switch(eventCode)
{
case NSStreamEventOpenCompleted:
{
printf("EVENT: Open completed.\n");

if(stream == receiveStream)
{
printf("Receiving...\n");
}

if(stream == sendStream)
{
printf("Sending...\n");

NSString * strBuffer = [NSString stringWithFormat:@"GET / HTTP/1.0\r\n\r\n"];
const uint8_t * rawstring = (const uint8_t *)[strBuffer UTF8String];

[sendStream write:rawstring maxLength:strlen(rawstring)];
}

break;
}
case NSStreamEventEndEncountered:
{
printf("EVENT: End encountered.\n");
break;
}
case NSStreamEventHasSpaceAvailable:
{
printf("EVENT: Has space available.\n");
break;
}
case NSStreamEventHasBytesAvailable:
{
printf("EVENT: Has bytes available.\n");
break;
}
case NSStreamEventErrorOccurred:
{
printf("EVENT: Error occurred.\n");
break;
}
case NSStreamEventNone:
{
printf("EVENT: None.\n");
break;
}
}

printf("EVENT: End.\n");
}

-(void) close
{
[receiveStream close];
[sendStream close];

printf("Closed.\n");
}

@end