首页 > 代码库 > OC中的socket通信

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 =http://www.mamicode.com/ [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就可以建立连接了