// // Socketxxxx.m // HeBeiFM // // Created by Apple on 16/9/22. // Copyright © 2016年 Apple. All rights reserved. // #import "Socket.h" /** 用于处理socket接收的数据 */ #import "DataControl.h" /** socket掉线重连处理 */ #import "ReconnectControl.h" #import "NSString+HexToBytes.h" //#import "DeviceModel.h" @interface Socket () { VoidBlock _block; NSTimer *_connectTimer; // 计时器,用于心跳连接 NSInteger _dataTag; //DeviceModel * currentModel; } @end @implementation Socket /** 单利模式 */ +(Socket *) sharedInstance { static Socket *sharedInstace = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstace = [[self alloc] init]; }); return sharedInstace; } // socket连接 -(void)socketConnectHost:(VoidBlock)block { //数据处理类清楚历史数据 [[DataControl shareControl] clearData]; //回调方法 _block = block; //连接socket self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; NSError *error = nil; [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error]; } /** 连接成功 */ -(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port { if (_block) { _block(); } //读取socket中的数据 [self readData]; //currentModel = [[DeviceModel alloc] init]; // 每隔30s像服务器发送心跳包 _connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];// 在longConnectToSocket方法中进行长连接需要向服务器发送的讯息 [_connectTimer fire]; } // 切断socket -(void)cutOffSocket { self.socket.userData = SocketOfflineByUser;// 声明是由用户主动切断 self.socket.delegate = nil; [_connectTimer invalidate]; [self.socket disconnect]; self.socket.userData = SocketOfflineByUser;// 声明是由用户主动切断 [[DataControl shareControl] clearData]; } //socket掉线,掉线后进行掉线重新连接流程,由SocketReconnectControl类处理 -(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { NSLog(@"服务器断开连接 socket.userData = %@",sock.userData); if ([sock.userData isEqualToString:SocketOfflineByUser]) { return; } else if([sock.userData isEqualToString:SocketOfflineByServer]) { [self reconnectSocket]; } } -(void)reconnectSocket { [[ReconnectControl shareControl] startReconnectBlock:^{ [[NSNotificationCenter defaultCenter] postNotificationName:SocketConnectErrorNotification object:nil]; } success:^{ [[NSNotificationCenter defaultCenter] postNotificationName:SocketConnectSuccessNotification object:nil]; }]; } // 心跳连接 -(void)longConnectToSocket { // 根据服务器要求发送固定格式的数据,假设为指令@".",但是一般不会是这么简单的指令 NSString *longConnect = @".\n"; //NSData *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding]; // byte[] data = new byte[12]; // data[0] = (byte) 0x9c; // data[1] = (byte) 0x00; // data[2] = (byte) 0x00; // data[3] = (byte) 0x01; // data[4] = (byte) 0x00; // data[5] = (byte) 0x01; // data[6] = (byte) 0xf0; // data[7] = (byte) 0xfe; // data[8] = (byte) 0x6b; // data[9] = (byte) 0x15; // data[10] = (byte) 0x6e; // data[11] = (byte) 0xb7; Byte *data = (Byte*)malloc(12); data[0] = 0x9c; data[1] = 0x00; data[2] = 0x00; data[3] = 0x01; data[4] = 0x00; data[5] = 0x01; // mac 地址 //NSData* bytes = [_selectedDevice.mac hexToBytes]; //Byte * myByte = (Byte *)[bytes bytes]; //NSLog(@"myByte = %s",myByte); //memcpy(data+6, [bytes bytes], [bytes length]); // NSUInteger len = [_currentData length]; // Byte *byteData = (Byte*)malloc(len); // memcpy(byteData, [_currentData bytes], len); // data[6] = 0xf0; // data[7] = 0xfe; // data[8] = 0x6b; // data[9] = 0x15; // data[10] = 0x6e; // data[11] = 0xb7; // for( NSUInteger i = 0; i < 12; i++ ) // { // NSLog(@"第%ld个数字:%x",i,data[i]); // } NSData *dataStream = [NSData dataWithBytes: data length: 12]; [self writeData:dataStream]; free(data); data = nil; } /** 收到服务器的数据,读取数据成功后通过SocketDataControl处理,防止粘包 */ -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { [self readData]; NSLog(@"读取成功"); //__block DeviceModel *arr = [DeviceModel new]; NSUInteger len = [data length]; Byte *byteData = (Byte*)malloc(len); memcpy(byteData, [data bytes], len); //currentModel.x6 = [NSString stringWithFormat:@"%d",byteData[22]]; // currentModel.x7 = [NSString stringWithFormat:@"%d",byteData[23]]; // currentModel.x8 = [NSString stringWithFormat:@"%d",byteData[24]]; // currentModel.x5 = [NSString stringWithFormat:@"%d",byteData[21]]; // currentModel.x1 = [NSString stringWithFormat:@"%d",byteData[14]*256+byteData[15]]; // currentModel.x9 = [NSString stringWithFormat:@"%d",byteData[25]]; // currentModel.x10 = [NSString stringWithFormat:@"%d",byteData[26]]; // currentModel.x11 = [NSString stringWithFormat:@"%d",byteData[27]]; // currentModel.x12 = [NSString stringWithFormat:@"%d",byteData[28]]; // currentModel.x13 = [NSString stringWithFormat:@"%d",byteData[29]]; //[self performSelector:@selector(sendMessage:) withObject:currentModel]; free(byteData); byteData = nil; // [[DataControl shareControl] appendingData:data newData:^(DeviceModel *models) // { // [self performSelector:@selector(sendMessage:) withObject:models]; // //arr = models; // }]; } /** 读取数据方法 */ -(void)readData { _dataTag +=1; [self.socket readDataWithTimeout:-1 tag:_dataTag]; } /** 写入数据方法 */ -(void)writeData:(NSData*)data { _dataTag += 1; [_socket writeData:data withTimeout:-1 tag:_dataTag]; } -(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag { NSLog(@"Socket写入成功"); } /** 获取网络状态,网络状态由AFN获取,当网路断开时直接通知UI断网 */ -(void)setNetStatus:(AFNetworkReachabilityStatus)netStatus { _netStatus = netStatus; if (netStatus == AFNetworkReachabilityStatusNotReachable) { [[NSNotificationCenter defaultCenter] postNotificationName:SocketConnectErrorNotification object:nil]; } else { if ([ReconnectControl shareControl].status == Reconnecting) { [[ReconnectControl shareControl] reconnect]; } } } //-(void)sendMessage:(DeviceModel*)messages //{ // [[NSNotificationCenter defaultCenter] postNotificationName:SocketNewMessageNotification object:messages]; //} @end