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