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

  • 相关阅读:
    无监督学习
    监督学习
    cmd
    oj1026
    oj1025
    使用虚函数的不同模式
    hdu1166:敌兵布阵(树状数组或线段树)
    传纸条(动态规划)
    SDUT 1266 出栈序列统计(卡特兰数)
    HDU 5063 Operation the Sequence
  • 原文地址:https://www.cnblogs.com/xyzaijing/p/3856101.html
Copyright © 2020-2023  润新知