//
|
// 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 ()<GCDAsyncSocketDelegate>
|
{
|
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
|