之前在<a href="http://www.jianshu.com/p/f0b9a76f9ae4">《智能开发(Socket篇一)》</a>的时候已经介绍过怎样用第三方框架 CocoaAsyncSocket
实现 TCP/IP 连接。现在,再介绍一种用原生的输入输出流来实现 socket 连接。
1、实现NSStreamDelegate
协议
这个是监听 socket 的连接、数据发送、数据接收以及连接断开的协议
- (void)stream:(NSStream *)aStream
handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventNone: {
NSLog(@"NSStreamEventNone");
break;
}
case NSStreamEventOpenCompleted: {
// 完成连接
NSLog(@"NSStreamEventOpenCompleted");
break;
}
case NSStreamEventHasBytesAvailable: {
// 有数据可读,即有数据从服务器传过来
NSLog(@"NSStreamEventHasBytesAvailable");
// 读数据
[self readData];
break;
}
case NSStreamEventHasSpaceAvailable: {
// 有数据发送
NSLog(@"NSStreamEventHasSpaceAvailable");
break;
}
case NSStreamEventErrorOccurred: {
// 不正常断开连接
NSLog(@"NSStreamEventErrorOccurred: %@",[aStream streamError]);
break;
}
case NSStreamEventEndEncountered: {
// 正常断开连接
NSLog(@"NSStreamEventEndEncountered");
break;
}
}
}
2、定义输入输出流实例变量
这两个变量就相当于架在客户端与服务器间的两条管,一条用于数据流出,另一条用于数据流入
{
NSOutputStream *_outputStream;
NSInputStream *_inputStream;
}
3、三次握手建立长连接
NSString *ip = @"127.0.0.1";
int port = 8080;
// 创建 C 类型输入输出
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
// 创建连接
CFStreamCreatePairWithSocketToHost(NULL,
(__bridge CFStringRef)(ip),
port,
&readStream,
&writeStream);
// 将 C 类型转成 OC 对象
_intputStream = (__bridge NSInputStream *)(readStream);
_outputStream = (__bridge NSOutputStream *)(writeStream);
// 释放 C 类型输入输出流
CFRelease(readStream);
CFRelease(writeStream);
// 将输入输出流添加到当前运行循环
[_intputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
// 设置 NSStreamDelegate 监听对象
_intputStream.delegate = self;
_outputStream.delegate = self;
// 打开输入输出监听
[_intputStream open];
[_outputStream open];
4、发送数据
NSData *data = [NSData dataWithBytes:"\x0a\x0d"
length:2];
[_outputStream write:data.bytes
maxLength:data.length];
5、读数据
- (void)readData {
// 建立一个 1024byte 的缓存区,一次最多可读 1024byte
uint8_t buff[1024];
// len 为实际读到的数据
NSInteger len = [_intputStream read:buff
maxLength:sizeof(buff)];
NSData *data = [NSData dataWithBytes:buff
length:len];
}
6、断开连接
[_intputStream close];
[_intputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[_outputStream close];
[_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];