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(有符号的字节类型)。数据类型不一样,会导致发生内容不正确,就不能接收到后台发来的数据。
浙公网安备 33010602011771号