iOS 長(zhǎng)鏈接WebSocket應(yīng)用之SocketRocket

Facebook家的SocketRocket應(yīng)該是OC語(yǔ)言里針對(duì)WebSocket最好的框架啦淑廊,因?yàn)闃I(yè)務(wù)需求院尔,我們把應(yīng)用的部分請(qǐng)求更換成了長(zhǎng)鏈接,以下是使用總結(jié)锥忿。


至于為什么要使用WebSocket?當(dāng)然是為了與服務(wù)器更方便快捷地進(jìn)行通訊怠肋,不用每次請(qǐng)求都得客戶端先給服務(wù)器發(fā)一個(gè)Request敬鬓,然后等待服務(wù)器對(duì)應(yīng)的response;而可以由服務(wù)端決定什么時(shí)候給你推送什么消息笙各,這點(diǎn)對(duì)于某些通信類的功能模塊是很方便的钉答。
如果你想深入了解下Websocket的原理,可以看這篇WebSocket 是什么原理杈抢?為什么可以實(shí)現(xiàn)持久連接数尿?

接下來(lái)談?wù)刉ebSocket的使用,因?yàn)檎麄€(gè)SocketRocket就只有一個(gè).h和.m文件惶楼,所以socket的使用也相對(duì)簡(jiǎn)單右蹦。

1.首先建造一個(gè)SocketRocketUtility單例以便整個(gè)項(xiàng)目使用WebSocket來(lái)通信

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

2.然后創(chuàng)建一個(gè)Socket來(lái)建立通信
在.m文件中添加類的Extension

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

創(chuàng)建socket并建立連接

   - (void) SRWebSocketOpen{
   self.socket =[[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: @"your string "]]];
   self.socket.delegate = self;
   [self.socket open];
}
  1. 然后處理socket連接的結(jié)果,監(jiān)聽(tīng)連接是否成功的回調(diào)

    #pragma mark - socket delegate
    

    如果連接建立成功

    - (void)webSocketDidOpen:(SRWebSocket *)webSocket {
     //開(kāi)啟心跳
     [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];
       }
     }
    

這里有個(gè)心跳規(guī)則歼捐,其實(shí)一般的Websocket的第三方框架會(huì)自帶這個(gè)并不需要自己做特別處理何陆,只要與服務(wù)器商量好時(shí)間,定時(shí)地向服務(wù)器發(fā)送ping消息豹储,服務(wù)器會(huì)返回相應(yīng)地pong消息贷盲,表示我們的連接還在

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

這里用了NSTimer,所以要注意對(duì)應(yīng)所在線程的runloop颂翼;正常情況下晃洒,將NSTimer添加到主線程的runloop中,為了確保這段代碼在主行程中執(zhí)行朦乏,我們添加一段宏

#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方法就是調(diào)用第三方框提供的方法

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

4.就是想服務(wù)器發(fā)送數(shù)據(jù)球及,一般跟服務(wù)器通信傳遞的數(shù)據(jù)是json格式,所以記得把之前字典里的信息以及服務(wù)器要求的一些相關(guān)字段轉(zhuǎn)換成json格式呻疹,然后send:

 - (void)sendData{
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         if (weakself.socket != nil) {
        // 只有 SR_OPEN 開(kāi)啟狀態(tài)才能調(diào) send 方法啊吃引,不然要崩
        if (weakself.socket.readyState == SR_OPEN) {
            [weakself.socket send:data];    // 發(fā)送數(shù)據(jù)
            
        } else if (weakself.socket.readyState == SR_CONNECTING) {      
            [self reConnect];
            
        } else if (weakself.socket.readyState == SR_CLOSING || weakself.socket.readyState == SR_CLOSED) {
            // websocket 斷開(kāi)了,調(diào)用 reConnect 方法重連
            [self reConnect];
        }
    } 
  else{
 //如果在發(fā)送數(shù)據(jù)刽锤,但是socket已經(jīng)關(guān)閉镊尺,可以在再次打開(kāi)
    [self SRWebSocketOpen];
}
 });
}

5.接收服務(wù)器信息

#pragma mark - 收到的回調(diào)
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message  {

if (webSocket == self.socket) {

    NSLog(@"message:%@",message);
    if(!message){
        return;
    }
  //收到的數(shù)據(jù)格式也是json格式的,可以用MJExtension里字典轉(zhuǎn)模型的方法更改為自定義的數(shù)據(jù)格式
 //這里要將接收到的消息專遞出去并思,可以用block或者通知的形式庐氮;個(gè)人偏好block一點(diǎn)
    [self handleReceivedMessage:message];

    }
}

6.關(guān)閉Socket連接
最后可以選擇在合適的時(shí)候關(guān)閉長(zhǎng)連接

-(void)SRWebSocketClose{
if (self.socket){
    [self.socket close];
    self.socket = nil;
    //斷開(kāi)連接時(shí)銷毀心跳
    [self destoryHeartBeat];
    }
}

具體代碼在這里 WebsocketDemo-iOS
這里推薦一個(gè)可用的Websocket在線測(cè)試網(wǎng)站:http://www.blue-zero.com/WebSocket/
表示可以看看我的star,對(duì)于一個(gè)程序員宋彼,我star里面的東西還是蠻不錯(cuò)噠

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弄砍,一起剝皮案震驚了整個(gè)濱河市仙畦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌音婶,老刑警劉巖慨畸,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異衣式,居然都是意外死亡寸士,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門碴卧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弱卡,“玉大人,你說(shuō)我怎么就攤上這事螟深⌒持妫” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵界弧,是天一觀的道長(zhǎng)凡蜻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)垢箕,這世上最難降的妖魔是什么划栓? 我笑而不...
    開(kāi)封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮条获,結(jié)果婚禮上忠荞,老公的妹妹穿的比我還像新娘。我一直安慰自己帅掘,他們只是感情好委煤,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著修档,像睡著了一般碧绞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吱窝,一...
    開(kāi)封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天讥邻,我揣著相機(jī)與錄音,去河邊找鬼院峡。 笑死兴使,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的照激。 我是一名探鬼主播发魄,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼俩垃!你這毒婦竟也來(lái)了欠母?” 一聲冷哼從身側(cè)響起欢策,我...
    開(kāi)封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赏淌,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體啄清,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡六水,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辣卒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掷贾。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖荣茫,靈堂內(nèi)的尸體忽然破棺而出想帅,到底是詐尸還是另有隱情,我是刑警寧澤啡莉,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布港准,位于F島的核電站,受9級(jí)特大地震影響咧欣,放射性物質(zhì)發(fā)生泄漏浅缸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一魄咕、第九天 我趴在偏房一處隱蔽的房頂上張望衩椒。 院中可真熱鬧,春花似錦哮兰、人聲如沸毛萌。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阁将。三九已至,卻和暖如春囤躁,著一層夾襖步出監(jiān)牢的瞬間冀痕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工狸演, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留言蛇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓宵距,卻偏偏與公主長(zhǎng)得像腊尚,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子满哪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容