[iOS] 接入WebSocket記錄 + 一些個人經(jīng)驗(yàn)

閑扯

WebSocket 以前沒用過糯崎,之前寫過一篇博客是基于原生socket的(查看)比較復(fù)雜河泳,慎入。今天另外一個APP需要接websocket了薄霜,然后便找到了facebook的 SocketRocket 框架纸兔,然后用了一天時間接上了食拜,完成了掉線自動重連,自動重登錄流强,心跳等等功能呻待,用法比原生socket簡單(原生socket基于TCP/UDP協(xié)議)。

為什么用 WebSocket

因?yàn)锳PP里面有個聊天功能奏篙,需要服務(wù)器主動推數(shù)據(jù)到APP。HTTP 通信方式只能由客戶端主動拉取为严,服務(wù)器不能主動推給客戶端第股,如果有實(shí)時的消息话原,要立刻通知客戶端就麻煩了,要么客戶端每隔幾秒鐘發(fā)一次請求涉馅,看看有沒有新數(shù)據(jù)黄虱,這種方式想想都知道耗流量電量。還一種方式就是走TCP/UDP協(xié)議服務(wù)器主動推給你盐捷,這種方式省流量默勾。還有就是用websocket,websocket是h5里面的東西滞诺,h5我不太會环疼,反正它比原生socket用法簡單。

用法

用 SocketRocket 框架淋叶,記住幾個代理方法就好了伪阶,很簡單栅贴。
1.創(chuàng)建和設(shè)置代理對象

SRWebSocket *socket = [[SRWebSocket alloc] initWithURLRequest:
[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://ip地址:端口"]];

socket.delegate = self;    // 實(shí)現(xiàn)這個 SRWebSocketDelegate 協(xié)議啊

[socket open];    // open 就是直接連接了

2.連接成功會調(diào)用這個代理方法

- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
    NSLog(@"連接成功,可以立刻登錄你公司后臺的服務(wù)器了凝赛,還有開啟心跳");
}

3.連接失敗會調(diào)用這個方法,看 NSLog 里面的東西

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
    NSLog(@"連接失敗捆昏,這里可以實(shí)現(xiàn)掉線自動重連屡立,要注意以下幾點(diǎn)");
    NSLog(@"1.判斷當(dāng)前網(wǎng)絡(luò)環(huán)境搀军,如果斷網(wǎng)了就不要連了勇皇,等待網(wǎng)絡(luò)到來敛摘,在發(fā)起重連");
    NSLog(@"2.判斷調(diào)用層是否需要連接,例如用戶都沒在聊天界面兄淫,連接上去浪費(fèi)流量");
    NSLog(@"3.連接次數(shù)限制捕虽,如果連接失敗了,重試10次左右就可以了房揭,不然就死循環(huán)了晌端。
    或者每隔1咧纠,2,4梧奢,8钧椰,10,10秒重連...f(x) = f(x-1) * 2, (x<5)  f(x)=10, (x>=5)");
}

4.連接關(guān)閉調(diào)用這個方法瓶埋,注意連接關(guān)閉不是連接斷開,關(guān)閉是 [socket close] 客戶端主動關(guān)閉,斷開可能是斷網(wǎng)了养筒,被動斷開的曾撤。

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
    NSLog(@"連接斷開,清空socket對象晕粪,清空該清空的東西挤悉,還有關(guān)閉心跳!");
}

5.收到服務(wù)器發(fā)來的數(shù)據(jù)會調(diào)用這個方法

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message  {
    NSLog(@"收到數(shù)據(jù)了巫湘,注意 message 是 id 類型的装悲,學(xué)過C語言的都知道,id 是 (void *)  
        void* 就厲害了尚氛,二進(jìn)制數(shù)據(jù)都可以指著诀诊,不詳細(xì)解釋 void* 了");
    NSLog(@"我這后臺約定的 message 是 json 格式數(shù)據(jù)
        收到數(shù)據(jù)阅嘶,就按格式解析吧属瓣,然后把數(shù)據(jù)發(fā)給調(diào)用層");
}

6.向服務(wù)器發(fā)送數(shù)據(jù)
發(fā)送的時候可能斷網(wǎng),可能socket還在連接讯柔,要判斷一些情況抡蛙,寫在下面了
發(fā)送邏輯是,我有一個 socketQueue 的串行隊列魂迄,發(fā)送請求會加到這個隊列里粗截,然后一個一個發(fā)出去,如果掉線了极祸,重連連上后繼續(xù)發(fā)送慈格,對調(diào)用層透明,調(diào)用層不需要知道網(wǎng)絡(luò)斷開了遥金。

- (void)sendData:(id)data {
    WEAKSELF(ws);
    dispatch_async(self.socketQueue, ^{
        if (ws.socket != nil) {
            // 只有 SR_OPEN 開啟狀態(tài)才能調(diào) send 方法啊浴捆,不然要崩
            if (ws.socket.readyState == SR_OPEN) {
                [ws.socket send:data];    // 發(fā)送數(shù)據(jù)

            } else if (ws.socket.readyState == SR_CONNECTING) {
                NSLog(@"正在連接中,重連后其他方法會去自動同步數(shù)據(jù)");
                // 每隔2秒檢測一次 socket.readyState 狀態(tài)稿械,檢測 10 次左右
                // 只要有一次狀態(tài)是 SR_OPEN 的就調(diào)用 [ws.socket send:data] 發(fā)送數(shù)據(jù)
                // 如果 10 次都還是沒連上的选泻,那這個發(fā)送請求就丟失了,這種情況是服務(wù)器的問題了美莫,小概率的
                // 代碼有點(diǎn)長页眯,我就寫個邏輯在這里好了

            } else if (ws.socket.readyState == SR_CLOSING || ws.socket.readyState == SR_CLOSED) {
                // websocket 斷開了,調(diào)用 reConnect 方法重連
                [ws reConnect:^{
                    NSLog(@"重連成功厢呵,繼續(xù)發(fā)送剛剛的數(shù)據(jù)");
                    [ws.socket send:data];
                }];
            }
        } else {
            NSLog(@"沒網(wǎng)絡(luò)窝撵,發(fā)送失敗,一旦斷網(wǎng) socket 會被我設(shè)置 nil 的");
            NSLog(@"其實(shí)最好是發(fā)送前判斷一下網(wǎng)絡(luò)狀態(tài)比較好襟铭,我寫的有點(diǎn)晦澀碌奉,socket==nil來表示斷網(wǎng)");
        }
    });
}

7.心跳機(jī)制
心跳機(jī)制就不難了短曾,開個定時器,問下后臺要每隔多少秒發(fā)送一次心跳請求就好了赐劣。然后注意嫉拐,斷網(wǎng)了或者socket斷開的時候把心跳關(guān)一下,省資源魁兼,不然都斷網(wǎng)了婉徘,還在循環(huán)發(fā)心跳,浪費(fèi)CPU和電量咐汞。

8.終于接完websocket了盖呼,下班回家壓壓驚。我第一次用碉考,其實(shí)不難塌计,就是考慮的情況比較多挺身,整個邏輯有點(diǎn)多侯谁,主要代碼就是上面那些了,其他不重要的代碼我就不復(fù)制粘貼上來了章钾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末墙贱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贱傀,更是在濱河造成了極大的恐慌惨撇,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件府寒,死亡現(xiàn)場離奇詭異魁衙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)株搔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門剖淀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纤房,你說我怎么就攤上這事纵隔。” “怎么了炮姨?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵捌刮,是天一觀的道長。 經(jīng)常有香客問我舒岸,道長绅作,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任蛾派,我火速辦了婚禮俄认,結(jié)果婚禮上堕扶,老公的妹妹穿的比我還像新娘。我一直安慰自己梭依,他們只是感情好稍算,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著役拴,像睡著了一般糊探。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上河闰,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天科平,我揣著相機(jī)與錄音,去河邊找鬼姜性。 笑死瞪慧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的部念。 我是一名探鬼主播弃酌,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼儡炼!你這毒婦竟也來了妓湘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤乌询,失蹤者是張志新(化名)和其女友劉穎榜贴,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妹田,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唬党,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鬼佣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驶拱。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沮趣,靈堂內(nèi)的尸體忽然破棺而出屯烦,到底是詐尸還是另有隱情,我是刑警寧澤房铭,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布驻龟,位于F島的核電站,受9級特大地震影響缸匪,放射性物質(zhì)發(fā)生泄漏翁狐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一凌蔬、第九天 我趴在偏房一處隱蔽的房頂上張望露懒。 院中可真熱鬧闯冷,春花似錦、人聲如沸懈词。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坎弯。三九已至纺涤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抠忘,已是汗流浹背撩炊。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留崎脉,地道東北人拧咳。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像囚灼,于是被迫代替她去往敵國和親骆膝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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