// // 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" @interface Socket () { VoidBlock _block; NSTimer *_connectTimer; // 计时器,用于心跳连接 NSInteger _dataTag; } @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]; // 每隔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; data[6] = 0xf0; data[7] = 0xfe; data[8] = 0x6b; data[9] = 0x15; data[10] = 0x6e; data[11] = 0xb7; NSData *dataStream = [NSData dataWithBytes: data length: 12]; [self writeData:dataStream]; } /** 收到服务器的数据,读取数据成功后通过SocketDataControl处理,防止粘包 */ -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { [self readData]; NSLog(@"读取成功"); __block NSMutableArray *arr = [NSMutableArray new]; [[DataControl shareControl] appendingData:data newData:^(NSMutableArray *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:(NSMutableArray*)messages { [[NSNotificationCenter defaultCenter] postNotificationName:SocketNewMessageNotification object:messages]; } @end