美文网首页
2019-05-10

2019-05-10

作者: 策马的子乔 | 来源:发表于2019-05-10 09:30 被阅读0次

    最近在做项目时,用到socket,推送行情数据,达到数据实时更新的目的。为了节约时间和成本,便使用轮子CocoaAsyncSocket框架,采用TCP连接进行数据传输。和后台约定采用自定义协议,采用byte方式传输,数据格式如下:

    后台定义的socket包格式如下:

    根据后台的要求,必须使用byte进行数据传输,所以必须对int和NSString转换成byte(字节),最后把byte转换成NSData进行拼接,使用socket传给后台,下面是核心实现代码:

    - (void)connectSocket

    {

        //判断是否登录

        if (![XBUserInfo manage].sessionKey) {

            return;

        }

        NSString *host = @"socket地址";

        UInt32 port = 端口号;

        //创建GCDAsyncSocket

        NSError *error = nil;

        [self.socket connectToHost:host onPort:port error:&error];

        if (error != nil) {

            NSLog(@"%@",error);

        }

        //初始化,和服务器建立连接

        SignedByte protocolByte = 0x02;//协议编号

        SignedByte stateCodebyte = 0x01;//状态码

        //登录data

        NSDictionary *dict = @{@"token":[XBUserInfo manage].sessionKey,@"deviceFlag":@(1)};

        //发送登录的byte数据包

        [self sendMsgWithProtocolByte:protocolByte stateCodebyte:stateCodebyte content:dict];

    }

    - (void)sendMsgWithProtocolByte:(SignedByte)protocolByte stateCodebyte:(SignedByte)stateCodebyte content:(id)content

    {

      //协议编号

        NSData *protocolData = [NSData oneByteToData:protocolByte];//自定义的字节转data方法

    //状态码

        NSData * stateCodebyteData = [NSData oneByteToData:stateCodebyte];//自定义的字节转data方法

        NSData  *loginbyteData;

        if ([content isKindOfClass:[NSDictionary class]]) {//协议编号为登录的data

            NSDictionary *dict = (NSDictionary *)content;

            NSString *loginStr = [NSString dictionaryToJson:dict];

            NSData *loginData = [loginStr dataUsingEncoding:NSUTF8StringEncoding];

            SignedByte *loginbyte = (SignedByte *)[loginData bytes];

          loginbyteData = [NSData dataWithBytes:loginbyte length:loginData.length];

        }else if ([content isKindOfClass:[NSString class]]){//协议编号为心跳包的data

            NSString *loginStr = (NSString *)content;

            NSData *loginData = [loginStr dataUsingEncoding:NSUTF8StringEncoding];

            SignedByte *loginbyte = (SignedByte *)[loginData bytes];

          loginbyteData = [NSData dataWithBytes:loginbyte length:loginData.length];

            NSLog(@"loginStr------------------------------%lu",(unsigned long)loginStr.length);

        }

        //消息长度

        int len =(int)loginbyteData.length;

        NSData *lengthData =  [NSData intToByte:len];//自定义的int转data方法

        NSMutableData *data = [NSMutableData data];

        [data appendData:protocolData];//协议编号

        [data appendData:stateCodebyteData];//状态码

        [data appendData:lengthData];//消息长度

        [data appendData:loginbyteData];//内容

        [self.socket  writeData:data withTimeout:-1 tag:111];

        [self.socket  readDataWithTimeout:-1 tag:101];

    }

    #pragma mark socket delegate

    -(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{

        NSLog(@"====>连接成功");

        [self threadStart];

        [self.socket  readDataWithTimeout:-1 tag:101];

    }

    -(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{

        NSLog(@"====>断开连接");

        [self connectSocket];

        [self.socket  readDataWithTimeout:-1 tag:101];

    }

    -(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{

        NSLog(@"====>写入成功,是否连接失败:====>%d",self.socket.isDisconnected);

        [self.socket  readDataWithTimeout:-1 tag:tag];

    }

    -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{

          NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

          NSLog(@"收到的数据:------------------%@",receiverStr);

        [self.socket  readDataWithTimeout:-1 tag:tag];

    }

    //心跳包发送

    - (void)threadStart

    {

        if (!_connectTimer) {

            self.connectTimer =  [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(heartBeat) userInfo:nil repeats:YES];

            [[NSRunLoop mainRunLoop] addTimer: self.connectTimer forMode:NSDefaultRunLoopMode];

        }

    }

    - (void)heartBeat

    {

        NSLog(@"~~~开始心跳了~~~");

        SignedByte protocolByte = 0x01;//协议编号为心跳包

        SignedByte stateCodebyte = 0x01;//状态码

        [self sendMsgWithProtocolByte:protocolByte stateCodebyte:stateCodebyte content:@""];

    }

    遇到的最大的坑:声明Byte类型时,应和后台保持一持,这里后台使用的是SignedByte(有符号的字节类型)。数据类型不一样,会导致发生内容不正确,就不能接收到后台发来的数据。

    ---------------------

    作者:码农甲乙丙

    来源:CSDN

    原文:https://blog.csdn.net/u012852597/article/details/81951592

    版权声明:本文为博主原创文章,转载请附上博文链接!

    相关文章

      网友评论

          本文标题:2019-05-10

          本文链接:https://www.haomeiwen.com/subject/rdlooqtx.html