Skip to content

Commit

Permalink
Add NSStream demo
Browse files Browse the repository at this point in the history
  • Loading branch information
kesalin committed Apr 15, 2013
1 parent 6a9f9bf commit a6b52e7
Show file tree
Hide file tree
Showing 9 changed files with 1,401 additions and 5 deletions.
16 changes: 16 additions & 0 deletions KSNetworkDemo/KSNetworkDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
213E2F001718FCEB00C62471 /* KSViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 213E2EFF1718FCEB00C62471 /* KSViewController.m */; };
213E2F0B1719042200C62471 /* KSSocketViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 213E2F091719042200C62471 /* KSSocketViewController.m */; };
213E2F0C1719042200C62471 /* KSSocketViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 213E2F0A1719042200C62471 /* KSSocketViewController.xib */; };
21A2522D171B791500882576 /* NSStream+StreamsToHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 21A2522C171B791500882576 /* NSStream+StreamsToHost.m */; };
21A25231171B79D800882576 /* KSNSStreamViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21A2522F171B79D800882576 /* KSNSStreamViewController.m */; };
21A25232171B79D800882576 /* KSNSStreamViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 21A25230171B79D800882576 /* KSNSStreamViewController.xib */; };
21F36B5D171999FC006B9932 /* KSCFNetworkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21F36B5B171999FB006B9932 /* KSCFNetworkViewController.m */; };
21F36B5E171999FC006B9932 /* KSCFNetworkViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 21F36B5C171999FC006B9932 /* KSCFNetworkViewController.xib */; };
/* End PBXBuildFile section */
Expand All @@ -44,6 +47,11 @@
213E2F081719042200C62471 /* KSSocketViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSSocketViewController.h; sourceTree = "<group>"; };
213E2F091719042200C62471 /* KSSocketViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSSocketViewController.m; sourceTree = "<group>"; };
213E2F0A1719042200C62471 /* KSSocketViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSSocketViewController.xib; sourceTree = "<group>"; };
21A2522B171B791500882576 /* NSStream+StreamsToHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSStream+StreamsToHost.h"; sourceTree = "<group>"; };
21A2522C171B791500882576 /* NSStream+StreamsToHost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSStream+StreamsToHost.m"; sourceTree = "<group>"; };
21A2522E171B79D800882576 /* KSNSStreamViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSNSStreamViewController.h; sourceTree = "<group>"; };
21A2522F171B79D800882576 /* KSNSStreamViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSNSStreamViewController.m; sourceTree = "<group>"; };
21A25230171B79D800882576 /* KSNSStreamViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSNSStreamViewController.xib; sourceTree = "<group>"; };
21F36B5A171999FB006B9932 /* KSCFNetworkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSCFNetworkViewController.h; sourceTree = "<group>"; };
21F36B5B171999FB006B9932 /* KSCFNetworkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSCFNetworkViewController.m; sourceTree = "<group>"; };
21F36B5C171999FC006B9932 /* KSCFNetworkViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSCFNetworkViewController.xib; sourceTree = "<group>"; };
Expand Down Expand Up @@ -95,6 +103,8 @@
children = (
213E2EF21718FCEB00C62471 /* KSAppDelegate.h */,
213E2EF31718FCEB00C62471 /* KSAppDelegate.m */,
21A2522B171B791500882576 /* NSStream+StreamsToHost.h */,
21A2522C171B791500882576 /* NSStream+StreamsToHost.m */,
213E2F071718FD1800C62471 /* Controllers */,
213E2F061718FD0100C62471 /* Resources */,
213E2EEA1718FCEB00C62471 /* Supporting Files */,
Expand All @@ -119,6 +129,7 @@
213E2F061718FD0100C62471 /* Resources */ = {
isa = PBXGroup;
children = (
21A25230171B79D800882576 /* KSNSStreamViewController.xib */,
21F36B5C171999FC006B9932 /* KSCFNetworkViewController.xib */,
213E2F0A1719042200C62471 /* KSSocketViewController.xib */,
213E2EFB1718FCEB00C62471 /* MainStoryboard.storyboard */,
Expand All @@ -135,6 +146,8 @@
213E2F091719042200C62471 /* KSSocketViewController.m */,
21F36B5A171999FB006B9932 /* KSCFNetworkViewController.h */,
21F36B5B171999FB006B9932 /* KSCFNetworkViewController.m */,
21A2522E171B79D800882576 /* KSNSStreamViewController.h */,
21A2522F171B79D800882576 /* KSNSStreamViewController.m */,
);
name = Controllers;
sourceTree = "<group>";
Expand Down Expand Up @@ -198,6 +211,7 @@
213E2EFD1718FCEB00C62471 /* MainStoryboard.storyboard in Resources */,
213E2F0C1719042200C62471 /* KSSocketViewController.xib in Resources */,
21F36B5E171999FC006B9932 /* KSCFNetworkViewController.xib in Resources */,
21A25232171B79D800882576 /* KSNSStreamViewController.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -213,6 +227,8 @@
213E2F001718FCEB00C62471 /* KSViewController.m in Sources */,
213E2F0B1719042200C62471 /* KSSocketViewController.m in Sources */,
21F36B5D171999FC006B9932 /* KSCFNetworkViewController.m in Sources */,
21A2522D171B791500882576 /* NSStream+StreamsToHost.m in Sources */,
21A25231171B79D800882576 /* KSNSStreamViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
4 changes: 2 additions & 2 deletions KSNetworkDemo/KSNetworkDemo/KSCFNetworkViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ - (void)networkFailedWithErrorMessage:(NSString *)message
// Update UI
//
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"%@", message);
NSLog(@" >> %@", message);

self.receiveTextView.text = message;
self.connectButton.enabled = YES;
Expand All @@ -136,7 +136,7 @@ - (void)networkSucceedWithData:(NSData *)data
}

#pragma mark -
#pragma mark Socket
#pragma mark CFNetwork

- (void)didReceiveData:(NSData *)data {
if (_receivedData == nil) {
Expand Down
21 changes: 21 additions & 0 deletions KSNetworkDemo/KSNetworkDemo/KSNSStreamViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// KSNSStreamViewController.h
// KSNetworkDemo
//
// Created by kesalin on 15/4/13.
// Copyright (c) 2013 [email protected]. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface KSNSStreamViewController : UIViewController <UITextFieldDelegate,NSStreamDelegate>

@property (weak, nonatomic) IBOutlet UITextField *serverAddressTextField;
@property (weak, nonatomic) IBOutlet UITextField *serverPortTextField;
@property (weak, nonatomic) IBOutlet UITextView *receiveTextView;
@property (weak, nonatomic) IBOutlet UIButton *connectButton;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *networkActivityView;

- (IBAction)connectButtonClick:(id)sender;

@end
227 changes: 227 additions & 0 deletions KSNetworkDemo/KSNetworkDemo/KSNSStreamViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
//
// KSNSStreamViewController.m
// KSNetworkDemo
//
// Created by kesalin on 15/4/13.
// Copyright (c) 2013 [email protected]. All rights reserved.
//

#import "KSNSStreamViewController.h"
#import "NSStream+StreamsToHost.h"

#define kBufferSize 1024

// See http://www.telnet.org/htm/places.htm
//
#define kTestHost @"telnet://towel.blinkenlights.nl"
#define kTestPort 23

@interface KSNSStreamViewController ()
{
NSMutableData * _receivedData;
}

@end

@implementation KSNSStreamViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

self.title = @"NSStream";

self.serverAddressTextField.delegate = self;
self.serverPortTextField.delegate = self;

self.serverAddressTextField.text = kTestHost;
self.serverPortTextField.text = [[NSNumber numberWithInt:kTestPort] stringValue];
self.receiveTextView.text = @"";
self.receiveTextView.editable = NO;
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
BOOL didResign = [textField resignFirstResponder];
return didResign;
}

- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message
{
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:@"Dismiss"
otherButtonTitles:nil];
[alert show];
}

- (IBAction)connectButtonClick:(id)sender
{
NSString * serverHost = self.serverAddressTextField.text;
NSString * serverPort = self.serverPortTextField.text;

if (serverHost == nil || [serverHost isEqualToString:@""]) {
[self showAlertWithTitle:@"Error" message:@"Server address cann't be empty!"];
return;
}

if (serverPort == nil || [serverPort isEqualToString:@""]) {
[self showAlertWithTitle:@"Error" message:@"Server port cann't be empty!"];
return;
}

self.connectButton.enabled = NO;
self.receiveTextView.text = @"Connecting to server...";
[self.networkActivityView startAnimating];

NSLog(@" >> main thread %@", [NSThread currentThread]);

NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", serverHost, serverPort]];
NSThread * backgroundThread = [[NSThread alloc] initWithTarget:self
selector:@selector(loadDataFromServerWithURL:)
object:url];
[backgroundThread start];
}

- (void)networkFailedWithErrorMessage:(NSString *)message
{
// Update UI
//
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@" >> %@", message);

self.receiveTextView.text = message;
self.connectButton.enabled = YES;
[self.networkActivityView stopAnimating];
}];
}

- (void)networkSucceedWithData:(NSData *)data
{
// Update UI
//
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSString * resultsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@" >> Received string: '%@'", resultsString);

self.receiveTextView.text = resultsString;
self.connectButton.enabled = YES;
[self.networkActivityView stopAnimating];
}];
}

#pragma mark -
#pragma mark NSStream

- (void)didReceiveData:(NSData *)data {
if (_receivedData == nil) {
_receivedData = [[NSMutableData alloc] init];
}

[_receivedData appendData:data];

// Update UI
//
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSString * resultsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
self.receiveTextView.text = resultsString;
}];
}

- (void)didFinishReceivingData
{
[self networkSucceedWithData:_receivedData];
}

- (void)loadDataFromServerWithURL:(NSURL *)url
{
NSInputStream * readStream;
[NSStream getStreamsToHostNamed:[url host]
port:[[url port] integerValue]
inputStream:&readStream
outputStream:NULL];

[readStream setDelegate:self];
[readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[readStream open];

[[NSRunLoop currentRunLoop] run];
}

#pragma mark NSStreamDelegate

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
NSLog(@" >> NSStreamDelegate in Thread %@", [NSThread currentThread]);

switch (eventCode) {
case NSStreamEventHasBytesAvailable: {
if (_receivedData == nil) {
_receivedData = [[NSMutableData alloc] init];
}

uint8_t buf[kBufferSize];
int numBytesRead = [(NSInputStream *)stream read:buf maxLength:1024];

if (numBytesRead > 0) {
[self didReceiveData:[NSData dataWithBytes:buf length:numBytesRead]];

} else if (numBytesRead == 0) {
NSLog(@" >> End of stream reached");

} else {
NSLog(@" >> Read error occurred");
}

break;
}

case NSStreamEventErrorOccurred: {
NSError * error = [stream streamError];
NSString * errorInfo = [NSString stringWithFormat:@"Failed while reading stream; error '%@' (code %d)", error.localizedDescription, error.code];

[self cleanUpStream:stream];

[self networkFailedWithErrorMessage:errorInfo];
}

case NSStreamEventEndEncountered: {

[self cleanUpStream:stream];

[self didFinishReceivingData];

break;
}

default:
break;
}
}

- (void)cleanUpStream:(NSStream *)stream
{
[stream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[stream close];

stream = nil;
}

@end
Loading

0 comments on commit a6b52e7

Please sign in to comment.