iOS 使用CocoaAsyncSocket自定义协议的byte方式传输

最近在做项目时,用到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(有符号的字节类型)。数据类型不一样,会导致发生内容不正确,就不能接收到后台发来的数据。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值