iOS 长链接WebSocket应用之SocketRocket

Facebook家的SocketRocket应该是OC语言里针对WebSocket最好的框架啦,因为业务需求,我们把应用的部分请求更换成了长链接,以下是使用总结。


至于为什么要使用WebSocket?当然是为了与服务器更方便快捷地进行通讯,不用每次请求都得客户端先给服务器发一个Request,然后等待服务器对应的response;而可以由服务端决定什么时候给你推送什么消息,这点对于某些通信类的功能模块是很方便的。
如果你想深入了解下Websocket的原理,可以看这篇WebSocket 是什么原理?为什么可以实现持久连接?

接下来谈谈WebSocket的使用,因为整个SocketRocket就只有一个.h和.m文件,所以socket的使用也相对简单。

1.首先建造一个SocketRocketUtility单例以便整个项目使用WebSocket来通信

@implementation SocketRocketUtility
+(SocketRocketUtility *)instance{
static SocketRocketUtility *Instance = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
    Instance = [[SocketRocketUtility alloc]init];
  }
}

2.然后创建一个Socket来建立通信
在.m文件中添加类的Extension

@interface SocketRocketUtility()<SRWebSocketDelegate>
@property (nonatomic, strong) SRWebSocket *socket;
@end

创建socket并建立连接

   - (void) SRWebSocketOpen{
   self.socket =[[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: @"your string "]]];
   self.socket.delegate = self;
   [self.socket open];
}
  1. 然后处理socket连接的结果,监听连接是否成功的回调

    #pragma mark - socket delegate
    

    如果连接建立成功

    - (void)webSocketDidOpen:(SRWebSocket *)webSocket {
     //开启心跳
     [self initHeartBeat];
     if (webSocket == self.socket) {
         NSLog(@"************************** socket 连接成功************************** ");
       }
     }
    

    如果连接建立失败

    - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
    
       if (webSocket == self.socket) {
       NSLog(@"************************** socket 连接失败************************** ");
       _socket = nil;
      //连接失败就重连
       [self reConnect];
       }
     }
    

这里有个心跳规则,其实一般的Websocket的第三方框架会自带这个并不需要自己做特别处理,只要与服务器商量好时间,定时地向服务器发送ping消息,服务器会返回相应地pong消息,表示我们的连接还在

- (void) initHeartBeat{
 heartBeat = [NSTimer timerWithTimeInterval:10 target:self selector:@selector(ping)  userInfo:nil repeats:YES];
 [[NSRunLoop currentRunLoop] addTimer:heartBeat forMode:NSRunLoopCommonModes];
 }

这里用了NSTimer,所以要注意对应所在线程的runloop;正常情况下,将NSTimer添加到主线程的runloop中,为了确保这段代码在主行程中执行,我们添加一段宏

#define dispatch_main_async_safe(block)\
if ([NSThread isMainThread]) {\
    block();\
} else {\
    dispatch_async(dispatch_get_main_queue(), block);\
}

然后将上面的代码改成

dispatch_main_async_safe(^{
     heartBeat = [NSTimer timerWithTimeInterval:10 target:self selector:@selector(ping) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop]addTimer:heartBeat forMode:NSRunLoopCommonModes];
})

具体的ping方法就是调用第三方框提供的方法

 - (void) ping{
if(self.socket.readyState == SR_OPEN){
  [self.socket sendPing:nil];
 }
}

4.就是想服务器发送数据,一般跟服务器通信传递的数据是json格式,所以记得把之前字典里的信息以及服务器要求的一些相关字段转换成json格式,然后send:

 - (void)sendData{
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         if (weakself.socket != nil) {
        // 只有 SR_OPEN 开启状态才能调 send 方法啊,不然要崩
        if (weakself.socket.readyState == SR_OPEN) {
            [weakself.socket send:data];    // 发送数据
            
        } else if (weakself.socket.readyState == SR_CONNECTING) {      
            [self reConnect];
            
        } else if (weakself.socket.readyState == SR_CLOSING || weakself.socket.readyState == SR_CLOSED) {
            // websocket 断开了,调用 reConnect 方法重连
            [self reConnect];
        }
    } 
  else{
 //如果在发送数据,但是socket已经关闭,可以在再次打开
    [self SRWebSocketOpen];
}
 });
}

5.接收服务器信息

#pragma mark - 收到的回调
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message  {

if (webSocket == self.socket) {

    NSLog(@"message:%@",message);
    if(!message){
        return;
    }
  //收到的数据格式也是json格式的,可以用MJExtension里字典转模型的方法更改为自定义的数据格式
 //这里要将接收到的消息专递出去,可以用block或者通知的形式;个人偏好block一点
    [self handleReceivedMessage:message];

    }
}

6.关闭Socket连接
最后可以选择在合适的时候关闭长连接

-(void)SRWebSocketClose{
if (self.socket){
    [self.socket close];
    self.socket = nil;
    //断开连接时销毁心跳
    [self destoryHeartBeat];
    }
}

具体代码在这里 WebsocketDemo-iOS
这里推荐一个可用的Websocket在线测试网站:http://www.blue-zero.com/WebSocket/
表示可以看看我的star,对于一个程序员,我star里面的东西还是蛮不错哒

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容