socket 连接
即时通讯最大的特点就是实时性,基本感觉不到延时或是掉线,所以必须对socket
的连接进行监视与检测,在断线时进行重新连接,如果用户退出登录,要将socket
手动关闭,否则对服务器会造成一定的负荷。
一般来说,一个用户(对于ios来说也就是我们的项目中)只能有一个正在连接的socket
,所以这个socket
变量必须是全局的,这里可以考虑使用单例或是AppDelegate
进行数据共享,本文使用单例。如果对一个已经连接的socket
对象再次进行连接操作,会抛出异常(不可对已经连接的socket
进行连接)程序崩溃,所以在连接socket
之前要对socket
对象的连接状态进行判断
一 下载完包结构
RunLoop
和GCD
两个文件夹中有两套
一种基于NSRunloop
,一种基于GCD
,后面讲的都是用基于GCD
的CocoaAsyncSocket
,因为RunLoop
中的将被废弃
1 |
__deprecated_msg("The RunLoop versions of CocoaAsyncSocket are deprecated and will be removed in a future release. Please migrate to GCDAsyncSocket.") |
二 项目中应用CocoaAsyncSocket
- 将
GCD
下四个文件拖入项目
1234GCDAsyncSocket.hGCDAsyncSocket.mGCDAsyncUdpSocket.hGCDAsyncUdpSocket.m - 创建单例类
1 2 3 4 |
// YHSocket.h @interface YHSocket : NSObject + (instancetype)sharedSocket; @end |
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 |
// YHSocket.m #import "YHSocket.h" #import "GCDAsyncSocket.h" @interface YHSocket () @property (nonatomic, strong) GCDAsyncSocket *asyncSocket; @end @implementation YHSocket + (instancetype)sharedSocket { static YHSocket *scoket; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ scoket = [[self alloc] init]; }); return scoket; } /* 全局队列(代理的方法是在子线程被调用) dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0) 主队列(代理的方法会在主线程被调用) dispatch_get_main_queue() 代理里的动作是耗时的动作,要在子线程中操作 代理里的动作不是耗时的动作,就可以在主线程中调用 看情况写队列 */ - (instancetype)init { if (self = [super init]) { _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; } return self; } |
- 然后写连接方法
添加端口和服务器地址属性
添加连接方法
1 2 3 4 5 6 7 8 9 10 |
// YHSocket.h @interface YHSocket : NSObject @property (nonatomic, assign) uint16_t port; // 端口 @property (nonatomic, copy) NSString *socketHost; // 服务器地址 + (instancetype)sharedSocket; - (void)startConnectSocket; @end |
实现
1 2 3 4 px !important; line-height: 15px !important;"> 1 2 3 4 一个正在连接的 socket ,所以这个socket 变量必须是全局的,这里可以考虑使用单例或是AppDelegate 进行数据共享,本文使用单例。如果对一个已经连接的socket 对象再次进行连接操作,会抛出异常(不可对已经连接的socket 进行连接)程序崩溃,所以在连接socket 之前要对socket 对象的连接状态进行判断
一 下载完包结构
二 项目中应用
|
1 2 3 4 |
GCDAsyncSocket.h GCDAsyncSocket.m GCDAsyncUdpSocket.h GCDAsyncUdpSocket.m |
1 2 3 4 |
// YHSocket.h @interface YHSocket : NSObject + (instancetype)sharedSocket; @end |
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 |
// YHSocket.m #import "YHSocket.h" #import "GCDAsyncSocket.h" @interface YHSocket () @property (nonatomic, strong) GCDAsyncSocket *asyncSocket; @end @implementation YHSocket + (instancetype)sharedSocket { static YHSocket *scoket; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ scoket = [[self alloc] init]; }); return scoket; } /* 全局队列(代理的方法是在子线程被调用) dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0) 主队列(代理的方法会在主线程被调用) dispatch_get_main_queue() 代理里的动作是耗时的动作,要在子线程中操作 代理里的动作不是耗时的动作,就可以在主线程中调用 看情况写队列 */ - (instancetype)init { if (self = [super init]) { _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; } return self; } |
- 然后写连接方法
添加端口和服务器地址属性
添加连接方法
1 2 3 4 5 6 7 8 9 10 |
// YHSocket.h @interface YHSocket : NSObject @property (nonatomic, assign) uint16_t port; // 端口 @property (nonatomic, copy) NSString *socketHost; // 服务器地址 + (instancetype)sharedSocket; - (void)startConnectSocket; @end |
实现
1 2 |