2019-05-10

最近在做项目时,用到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

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • iPhone的标准推荐是CFNetwork 库编程,其封装好的开源库是 cocoa AsyncSocket库,用它...
    Ethan_Struggle阅读 6,700评论 2 12
  • 转载:http://www.cocoachina.com/ios/20170615/19529.html 参考:h...
    F麦子阅读 9,481评论 3 2
  • 以流的方式处理IM通讯问题好处是无需多次建立连接,另外消息的网络开销少,而xmpp会有很多冗余的信息; 使用开源项...
    sea777777阅读 6,970评论 0 8
  • iOS开发系列--网络开发 概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博、微信等,这些应用本身可...
    lichengjin阅读 9,188评论 2 7
  • /**ios常见的几种加密方法: 普通的加密方法是讲密码进行加密后保存到用户偏好设置( [NSUserDefaul...
    彬至睢阳阅读 8,193评论 0 7