123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- //
- // UCWebSocketSever.m
- // wolfman
- //
- // Created by 张灿 on 2017/6/19.
- // Copyright © 2017年 shareSmile. All rights reserved.
- //
- #import "UCWebSocketSever.h"
- #import "UCSocketParmaModel.h"
- #import "SRSecurityPolicy.h"
- //通话已经取消(自己退出)
- @interface UCWebSocketSever()
- @property(nonatomic,strong)SRWebSocket* webSocket;
- @property(nonatomic,strong) dispatch_queue_t socketQueue;
- @property(nonatomic,copy)reconnectBlock reconnectblock;
- @property(nonatomic,assign)NSTimeInterval timeout;
- @property(nonatomic,strong)dispatch_source_t heartTimer;
- @property(nonatomic,assign)NSInteger reCount; //重连40次
- @end
- @implementation UCWebSocketSever
- +(instancetype)sharedWebSocketServer{
- static UCWebSocketSever* shareInstance = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- shareInstance = [[super allocWithZone:NULL]init];
-
- shareInstance.socketQueue = dispatch_queue_create("com.caicaicp.webSocket", nil);
- shareInstance.reCount = 0;
- });
- return shareInstance;
- }
- + (instancetype)allocWithZone:(struct _NSZone *)zone{
- return [UCWebSocketSever sharedWebSocketServer];
- }
- - (id)copyWithZone:(struct _NSZone *)zone
- {
- return [UCWebSocketSever sharedWebSocketServer];
- }
- - (void)startConnentWebSocket:(NSInteger)reconn {
- if (!self.webSocket) {
- NSString* urlString;
- urlString = [NSString stringWithFormat:@"%@&reconnect=%zd",self.serveUrl,reconn];
- NSLog(@"webSocket网址--%@",urlString);
- self.webSocket = [[SRWebSocket alloc]
- initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]] securityPolicy:[SRSecurityPolicy defaultPolicy]];
- self.webSocket.delegate = self;
- [self.webSocket open];
- }
- }
- - (void)removeDelegate{
- self.delegate = nil;
- }
- - (void)closeConnectWebSocket{
- [self.webSocket close];
- self.webSocket.delegate = nil;
- self.webSocket = nil;
- [self.timer invalidate]; // 将定时器从运行循环中移除,
- self.timer = nil;
- if (self.heartTimer) {
- dispatch_source_cancel(self.heartTimer);//删除GCD定时器
- self.heartTimer = nil;
- }
-
- }
- - (void)resetConnect{
- self.reCount++;
- [self closeConnectWebSocket];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self startConnentWebSocket:1];
- });
- }
- //连接成功回调
- - (void)webSocketDidOpen:(SRWebSocket *)webSocket {
- NSLog(@"连接成功");
- self.reCount = 0;
- NSLog(@"连接成功,可以立刻登录你公司后台的服务器了,还有开启心跳");
- if (!self.timer) {
- self.timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:@selector(sendHeartMsg:) userInfo:nil repeats:YES];
- [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
- }
- if (!self.heartTimer) {
- [self timePaddingStart];
- }
- if (self.reconnectblock) {
- self.reconnectblock();
- self.reconnectblock = nil;
- }
- }
- //连接失败回调
- - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
- NSLog(@"连接失败,这里可以实现掉线自动重连,要注意以下几点");
- NSLog(@"1.判断当前网络环境,如果断网了就不要连了,等待网络到来,在发起重连");
- NSLog(@"2.判断调用层是否需要连接,例如用户都没在聊天界面,连接上去浪费流量");
- //add by leo 弱网断开警告
- if (self.delegate&& [self.delegate respondsToSelector:@selector(weakNetWorkWaring)]) {
- // [self.delegate weakNetWorkWaring];
- }
- // if (self.reCount<40) {
- [self resetConnect];
- // }
- }
-
- //关闭连接回调的代理
- - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
- // if (code==1001) { //服务器断开 自动重连
- NSLog(@"服务器断开连接--code%zd--reson%@",code,reason);
- if (self.webSocket) {
- // if (self.reCount<40) {
- [self resetConnect];
- // }
- }
- // }else if(code==1005){//客户端自己手动断开
- //
- // }
- }
- //接收消息
- - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
- // NSLog(@"接收消息");
- if ([message isKindOfClass:[NSString class]]) {
- NSString* str = (NSString*)message;
- // NSLog(@"STR=%@",str);
- NSArray* array = [str componentsSeparatedByString:@"@@"];
- for (NSString* tempStr in array) {
- if (![tempStr isEqualToString:@""]) {
- UCPacketBody *body = [[UCPacketBody alloc] initWithData:[tempStr dataUsingEncoding:NSUTF8StringEncoding]];
- if (self.delegate&& [self.delegate respondsToSelector:@selector(didRecvMessage:)]) {
- [self.delegate didRecvMessage:body];
- }
- NSDictionary* dict = [body.data mj_JSONObject];
- UCSocketParmaModel* param = [UCSocketParmaModel mj_objectWithKeyValues:dict];
- if ([param.method isEqualToString:@"heartbeat"]) {
- //重置时间
- self.timeout = 40;
- }
- }
- }
- }
- }
- - (void)sendData:(NSData*)data{
- @weakify(self);
- dispatch_async(self.socketQueue, ^{
- @strongify(self);
- if (self.webSocket != nil) {
- // 只有 SR_OPEN 开启状态才能调 send 方法啊,不然要崩
- if (self.webSocket.readyState == SR_OPEN) {
- [self.webSocket sendData:data error:nil]; // 发送数据
- } else if (self.webSocket.readyState == SR_CONNECTING) {
- NSLog(@"正在连接中,重连后其他方法会去自动同步数据");
- // 每隔2秒检测一次 socket.readyState 状态,检测 10 次左右
- // 只要有一次状态是 SR_OPEN 的就调用 [ws.socket send:data] 发送数据
- // 如果 10 次都还是没连上的,那这个发送请求就丢失了,这种情况是服务器的问题了,小概率的
-
- } else if (self.webSocket.readyState == SR_CLOSING || self.webSocket.readyState == SR_CLOSED) {
- // websocket 断开了,调用 reConnect 方法重连
- [self reConnect:^{
- @strongify(self);
- [self.webSocket sendData:data error:nil];
- }];
- }
- } else {
- NSLog(@"webSocket已被清空");
- }
- });
- }
- //重新发送
- - (void)reConnect:(reconnectBlock)block{
- [self resetConnect];
- self.reconnectblock = block;
- }
- //发送心跳消息
- - (void)sendHeartMsg:(NSTimer*) theTimer
- {
- //发送心跳消息
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
- [dict setObject:@"heartbeat" forKey:@"method"];
- [dict setObject:@{@"room_id":self.roomId} forKey:@"data"];
- NSData* data = [dict mj_JSONData];
- if( [self.webSocket sendData:data error:nil]){
- NSLog(@"发送了心跳消息N");
- }
- }
- //收到心跳回复的倒计时
- - (void)timePaddingStart{
- self.timeout = 40;
- @weakify(self);
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
- self.heartTimer = timer;
- dispatch_source_set_timer(timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
- dispatch_source_set_event_handler(timer, ^{
- @strongify(self);
- if(self.timeout<=0){
- //没有收到心跳回调 重连if (self.webSocket.readyState!=SR_OPEN) {
- NSLog(@"没有收到回调,断开重连");
- // if (self.reCount<40) {
- [self resetConnect];
- // }
- }else{
- self.timeout--;
- }
- });
- dispatch_resume(timer);
-
- }
- @end
|