OC中的socket通信
现在很多客户端和服务器之间的交互都是通过JSON或者XML进行的,但是有时候如果数据量较小,JSON和XML就显得比较冗余
•Socket允许使用长连接,允许应用程序运行在异步模式(提高效率),只有在需要的时候才接收数据
•在iOS中以NSStream(流)来发送和接收数据
•可以设置流的代理,对流状态的变化做出相应
–连接建立
–接收到数据
–连接关闭
–
1.NSStream:数据流的父类,用于定义抽象特性,例如:打开、关闭代理,NSStream继承自CFStream(Core Foundation)
2.NSInputStream:NSStream的子类,用于读取输入
3.NSOutputStream:NSSTream的子类,用于写输出
下面是开发步骤:
1.网络连接设置
1).设置网络连接,绑定到主机和端口
2).设置输入流和输出流的代理,监听数据流的状态
3).将输入输出流添加至运行循环
4).打开输入流和输出流
2.发送消息给服务器
3.有可读取字节时,读取服务器返回的内容
4.到达流末尾时,关闭流,同时并从主运行循环中删除
废话不多说,下面我们来尝试使用以下Socket通信
首先定义输入流和输出流(PS.做过java开发的应该对输入输出流不陌生吧)
// 输入流,用来读取服务器返回的字节 NSInputStream *inputStream; // 输出流,用于给服务器发送字节 NSOutputStream *outputStream;
在OC中使用Socket需要用到CoreFoundation的一些流技术,创建流的时候需要用CFXXX等创建,然后在转换为NSXXX
下面是跟服务器建建立链接的方法
// 建立与服务器的连接 -(void)connectToServer:(NSString *)host port:(NSInteger)port{ // 创建CF下的读入流 CFReadStreamRef readStream; // 创建CF下的写出流 CFWriteStreamRef writeStream; // 创建流 CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(host), port, &readStream, &writeStream); // 将CFXXX流和NSXXX流建立对应关系 inputStream = (__bridge NSInputStream *)(readStream); outputStream = (__bridge NSOutputStream *)(writeStream); // 设置通信过程中的代理 inputStream.delegate = self; outputStream.delegate = self; // 将流对象添加到主运行循环(如果不加到主循环,Socket流是不会工作的) [inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; // 打开流 [inputStream open]; [outputStream open]; }
然后让你的类遵守NSStreamDelegate协议
并且实现下面的方法进行监听
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ NSLog(@"%u",eventCode); switch (eventCode) { case NSStreamEventOpenCompleted: NSLog(@"连接完成"); break; case NSStreamEventHasBytesAvailable: {NSLog(@"有刻度字节"); uint8_t buffer[10]; NSMutableString *mstr = [NSMutableString string]; int len;// = [inputStream read:buffer maxLength:sizeof(buffer)]; do{ len = [inputStream read:buffer maxLength:sizeof(buffer)]; NSString *s = [[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding]; [mstr appendString:s]; }while (len == sizeof(buffer)); NSLog(@"====%@====",mstr); } break; case NSStreamEventHasSpaceAvailable: NSLog(@"可以写入数据"); break; case NSStreamEventErrorOccurred: NSLog(@"发生错误"); break; case NSStreamEventEndEncountered: NSLog(@"流结束"); // 做善后工作 // 关闭流的同时,将流从主运行循环中删除 [aStream close]; [aStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; default: break; } }
调用connect方法后控制台就会打印出连接完成,可以写入数据,此时就可以写入数据了,下面是写入数据的代码
NSString *str = @"iam:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk12345"; NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; [outputStream write:data.bytes maxLength:data.length];
因为Socket传输的都是二进制流,所以当传输字符串时需要通过NSData转为二进制数据
此外要记得流关闭的时候要从主循环中移除
一般我们开发的时候不会用原生的socket,一般都是用第三方的框架,这样可以提高开发效率,减少开发过程中出现错误
如果使用的是TCP协议一般用AsyncUdpSocket如果使用的是UPD一般使用asyncUdpSockey
http://pan.baidu.com/s/1gdDuGIf
上面的地址中有我的demo和一个python写的服务脚本,,只需要在你的终端里面输入 python+空格+那个py文件就运行起来了.这个文件运行起来以后你的电脑就是一台服务器了,,连接服务器的代码里面host传127.0.0.1 port传12345就可以建立连接了