一究抓、基本概念
在iOS中以NSStream(流)來發(fā)送和接收數(shù)據(jù),可以設(shè)置流的代理,對流狀態(tài)的變化做出相應(yīng)啥刻。
1連接建立
2接收到數(shù)據(jù)
3連接關(guān)閉
NSStream:數(shù)據(jù)流的父類,用于定義抽象特性咪笑,例如:打開可帽、關(guān)閉代理,NSStream繼承自CFStream(CoreFoundation)
NSInputStream:NSStream的子類窗怒,用于讀取輸入
NSOutputStream:NSSTream的子類映跟,用于寫輸出
二、開發(fā)步驟
1扬虚、網(wǎng)絡(luò)連接設(shè)置
設(shè)置網(wǎng)絡(luò)連接努隙,綁定到主機(jī)和端口
設(shè)置輸入流和輸出流的代理,監(jiān)聽數(shù)據(jù)流的狀態(tài)
將輸入輸出流添加至運(yùn)行循環(huán)
打開輸入流和輸出流
2孔轴、發(fā)送消息給服務(wù)器
3剃法、有可讀取字節(jié)時,讀取服務(wù)器返回的內(nèi)容
4、到達(dá)流末尾時贷洲,關(guān)閉流收厨,同時并從主運(yùn)行循環(huán)中刪除
#import "ViewController.h"
@interface ViewController ()<NSStreamDelegate>{
NSInputStream *_inputStream;
NSOutputStream *_outputSteam;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)connectToServer:(id)sender {
//ios里實現(xiàn)sokcet的連接,使用C語言
// 1.與服務(wù)器通過三次握手建立連接
NSString *host = @"127.0.0.1";
int port = 12345;
// 2.定義輸入輸出流
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
// 3.分配輸入輸出流的內(nèi)存空間
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream);
// 4.把C語言的輸入輸出流轉(zhuǎn)成OC對象
_inputStream = (__bridge NSInputStream *)readStream;
_outputSteam = (__bridge NSOutputStream *)(writeStream);
// 5.設(shè)置代理,監(jiān)聽數(shù)據(jù)接收的狀態(tài)
_outputSteam.delegate = self;
_inputStream.delegate = self;
// 把輸入輸入流添加到主運(yùn)行循環(huán)(RunLoop)
// 主運(yùn)行循環(huán)是監(jiān)聽網(wǎng)絡(luò)狀態(tài)
[_outputSteam scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
// 6.打開輸入輸出流
[_inputStream open];
[_outputSteam open];
}
//代理的回調(diào)是在主線程
//NSLog(@"%@",[NSThread currentThread]);
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
// NSStreamEventOpenCompleted = 1UL << 0,
// NSStreamEventHasBytesAvailable = 1UL << 1,
// NSStreamEventHasSpaceAvailable = 1UL << 2,
// NSStreamEventErrorOccurred = 1UL << 3,
// NSStreamEventEndEncountered = 1UL << 4
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(@"%@",aStream);
NSLog(@"成功連接建立优构,形成輸入輸出流的傳輸通道");
break;
case NSStreamEventHasBytesAvailable:
NSLog(@"有數(shù)據(jù)可讀");
[self readData];
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"可以發(fā)送數(shù)據(jù)");
break;
case NSStreamEventErrorOccurred:
NSLog(@"有錯誤發(fā)生诵叁,連接失敗");
break;
case NSStreamEventEndEncountered:
NSLog(@"正常的斷開連接");
//把輸入輸入流關(guān)閉,而還要從主運(yùn)行循環(huán)移除
[_inputStream close];
[_outputSteam close];
[_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[_outputSteam removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
break;
default:
break;
}
}
- (IBAction)loginBtnClick:(id)sender {
//發(fā)送登錄請求 使用輸出流
//拼接登錄的指令 iam:zhangsan
NSString *loginStr = @"iam:zhangsan";
//uint8_t * 字符數(shù)組
NSData *data = [loginStr dataUsingEncoding:NSUTF8StringEncoding];
[_outputSteam write:data.bytes maxLength:data.length];
}
#pragma mark 讀取服務(wù)器返回的數(shù)據(jù)
-(void)readData{
//定義緩沖區(qū) 這個緩沖區(qū)只能存儲1024字節(jié)
uint8_t buf[1024];
// 讀取數(shù)據(jù)
// len為從服務(wù)器讀取到的實際字節(jié)數(shù)
NSInteger len = [_inputStream read:buf maxLength:sizeof(buf)];
// 把緩沖區(qū)里的實現(xiàn)字節(jié)數(shù)轉(zhuǎn)成字符串
NSString *receiverStr = [[NSString alloc] initWithBytes:buf length:len encoding:NSUTF8StringEncoding];
NSLog(@"%@",receiverStr);
}
@end