CocoaAsyncSocket框架的简单封装

在iOS开发中使用socket(CFNetwork),一般都是用第三方库AsyncSocket。

参考博客:http://my.oschina.net/worldligang/blog/396881?fromerr=WRR1ZAie

CocoaAsyncSocket的git下载地址:https://github.com/robbiehanson/CocoaAsyncSocket

下载CocoaAsyncSocket的文件,导入runloop中的AsyncSocket.h和AsyncSocket.m文件。

以下就是封装的CocoaAsyncSocket工具类DLSocketServe。

 1 //
 2 //  DLSocketServe.h
 3 //  AsnycSocketDemo
 4 //
 5 //  Created by wiseman on 15/12/23.
 6 //  Copyright (c) 2015年 wiseman. All rights reserved.
 7 //
 8 #import <Foundation/Foundation.h>
 9 #import "AsyncSocket.h"
10 
11 enum{
12     SocketOfflineByServer,      //服务器掉线
13     SocketOfflineByUser,        //用户断开
14     SocketOfflineByWifiCut,     //wifi 断开
15 };
16 
17 @interface DLSocketServe : NSObject<AsyncSocketDelegate>
18 
19 @property (strong,nonatomic) AsyncSocket * socket;
20 
21 @property (retain,nonatomic) NSTimer *heartTimer; //心跳计时器
22 
23 +(DLSocketServe *)sharedSocketServe;
24 
25 //socket连接
26 -(void)startConnetSocket;
27 
28 //断开socket连接
29 -(void)cutOffSocket;
30 
31 //发送消息
32 -(void)sendMessage:(id)message;
33 @end
  1 //
  2 //  DLSocketServe.m
  3 //  AsnycSocketDemo
  4 //
  5 //  Created by wiseman on 15/12/23.
  6 //  Copyright (c) 2015年 wiseman. All rights reserved.
  7 //
  8 
  9 
 10 #define HOST @"192.168.1.1"
 11 #define PORT 8080
 12 
 13 #define TIME_OUT 20
 14 
 15 //设置读取超时 -1 表示不会使用超时
 16 #define READ_TIME_OUT -1
 17 
 18 //设置写入超时 -1表示不会使用超时
 19 #define WRITW_TIME_OUT -1
 20 #define MAX_BUFFER 1024
 21 
 22 
 23 #import "DLSocketServe.h"
 24 
 25 @implementation DLSocketServe
 26 
 27 static DLSocketServe *socketServe = nil;
 28 
 29 //创建一个单例方法
 30 +(DLSocketServe *)sharedSocketServe{
 31     //@synchronized 的作用是创建一个互斥锁,保证此时没有其它线程对self对象进行修改。这个是objective-c的一个锁定令牌,防止self对象在同一时间内被其它线程访问,起到线程的保护作用。 一般在公用变量的时候使用,如单例模式或者操作类的static变量中使用。
 32     @synchronized(self){
 33         if(socketServe == nil) {
 34             socketServe = [[[self class] alloc] init];
 35         }
 36     }
 37     return socketServe;
 38 }
 39 
 40 +(instancetype)allocWithZone:(struct _NSZone *)zone{
 41     @synchronized(self){
 42         if (socketServe == nil) {
 43             socketServe = [super allocWithZone:zone];
 44             return socketServe;
 45         }
 46     }
 47     return nil;
 48 }
 49 
 50 -(void)startConnetSocket{
 51     self.socket = [[AsyncSocket alloc]initWithDelegate:self];
 52     [self.socket setRunLoopModes:@[NSRunLoopCommonModes]];
 53     if (![self SocketOpen:HOST port:PORT]) {
 54         
 55     }
 56 }
 57 
 58 -(NSInteger)SocketOpen:(NSString *)addr port:(NSInteger)port{
 59     if (!([self.socket isConnected])) {
 60         NSError *error = nil;
 61         [self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];
 62     }
 63     return 0;
 64 }
 65 
 66 
 67 //发送消息
 68 -(void)sendMessage:(id)message{
 69     //向服务器发送数据
 70     NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];
 71     [self.socket writeData:cmdData withTimeout:WRITW_TIME_OUT tag:1];
 72 }
 73 
 74 #pragma mark - AsyncSocket代理
 75 -(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
 76     NSLog(@"这是异步返回的连接成功");
 77     
 78     //通过定时器不断的发送消息,来检测长连接
 79     self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
 80     [self.heartTimer fire];
 81 }
 82 
 83 //心跳连接
 84 -(void)checkLongConnectByServe{
 85     //向服务器发送固定的消息,来检测长连接
 86     NSString *longConnect = @"connect is here";
 87     NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
 88     [self.socket writeData:data withTimeout:0 tag:0];
 89 }
 90 
 91 //断开连接
 92 //1.用户手动断开连接
 93 -(void)cutOffSocket{
 94     self.socket.userData = SocketOfflineByUser;
 95     //cutOffSocket 是用户断开连接之后,不在尝试重新连接
 96     [self.socket disconnect];
 97 }
 98 
 99 //2.wifi断开,socket断开连接
100 -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{
101     
102     NSData * unreadData = [sock unreadData]; // ** This gets the current buffer
103     if(unreadData.length > 0) {
104 //        socket出错会回调onSocket:willDisconnectWithError:方法,可以通过unreadData来读取未来得及读取的buffer。
105         [self onSocket:sock didReadData:unreadData withTag:0];
106         
107     } else {
108         
109         //wifi断开之后,会回调onSocket:willDisconnectWithError:方法,err.code == 57,这个时候设置self.socket.userData = SocketOfflineByWifiCut
110         NSLog(@" willDisconnectWithError %ld   err = %@",sock.userData,[err description]);
111         if (err.code == 57) {
112             self.socket.userData = SocketOfflineByWifiCut;
113         }
114 
115     }
116     
117 }
118 
119 //重新连接
120 //socket断开之后会回调  在onSocketDidDisconnect回调方法里面,会根据self.socket.userData来判断是否需要重新连接。
121 -(void)onSocketDidDisconnect:(AsyncSocket *)sock{
122     NSLog(@"%ld",sock.userData);
123     if (sock.userData == SocketOfflineByServer) {
124         //服务器掉线,重连
125         [self startConnetSocket];
126     }
127     else if (sock.userData == SocketOfflineByUser){
128         //如果由用户断开,不进行重连
129         return;
130     }
131     else if (sock.userData == SocketOfflineByWifiCut){
132         //wifi断开,不进行重连
133         return;
134     }
135 }
136 
137 
138 //发送消息成功之后回调
139 -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{
140     //发送消息成功之后会调用onSocket:didWriteDataWithTag:,在这个方法里可以进行读取消息。
141     //读取消息
142     [self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
143 }
144 
145 //接受消息成功之后回调
146 -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
147     //服务端返回消息数据量比较大时,可能分多次返回。所以在读取消息的时候,设置MAX_BUFFER表示每次最多读取多少,当data.length < MAX_BUFFER我们认为有可能是接受完一个完整的消息,然后才解析
148     
149     if (data.length < MAX_BUFFER) {
150         //收到结果解析
151         NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
152         NSLog(@"%@",dic);
153         //解析出来的消息,可以通过通知,代理,block等传递出去
154         
155     }
156     
157     [self.socket readDataWithTimeout:READ_TIME_OUT buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
158     
159 }
160 
161 - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
162 {
163     NSLog(@"didAcceptNewSocket");
164 }
165 
166 
167 
168 @end

封装好之后,使用:

导入:#import "DLSocketServe.h"

1 DLSocketServe *socketServe = [DLSocketServe sharedSocketServe];
2 //socket连接前先断开连接以免之前socket连接没有断开导致闪退
3 [socketServe cutOffSocket];
4 socketServe.socket.userData = SocketOfflineByServer;
5 [socketServe startConnectSocket];
6 
7 //发送消息 @"hahaha"只是举个列子,具体根据服务端的消息格式
8 [socketServe sendMessage:@"hahaha"];
原文地址:https://www.cnblogs.com/iOSDeng/p/5072903.html