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就可以建立连接了

posted @ 2014-07-20 12:46  784692237  阅读(4206)  评论(0编辑  收藏  举报