单军华
2017-03-08 5fda93834efe5d08227712c07c9a580e8f123f01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//
//  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