Socket.io 深入理解
最近在做項(xiàng)目?jī)?yōu)化工作時(shí),用到了Socket.io , Socket.io 文檔比較少, 結(jié)合官網(wǎng)介紹以及自己在項(xiàng)目開(kāi)發(fā)中的摸索,總結(jié)如下內(nèi)容;
Socket.io將Websocket和輪詢(xún) (Polling)機(jī)制以及其它的實(shí)時(shí)通信方式封裝成了通用的接口,并且在服務(wù)端實(shí)現(xiàn)了這些實(shí)時(shí)機(jī)制的相應(yīng)代碼。也就是說(shuō),Websocket僅僅是Socket.io實(shí)現(xiàn)實(shí)時(shí)通信的一個(gè)子集;
Socket.io 支持如下方式的通信方式,根據(jù)瀏覽器的支持程度,自動(dòng)選擇使用哪種技術(shù)進(jìn)行通信:
- WebSocket
- Flash Socket
- AJAX long-polling
- AJAX multipart streaming
- Forever IFrame
- JSONP polling
Socket.io 底層是 Engine.io; Engine.io作為Socket.io的服務(wù)器和瀏覽器之間交換的數(shù)據(jù)的傳輸層,實(shí)現(xiàn)了跨平臺(tái)的雙向通信。但是它不會(huì)取代Socket.io,它只是抽象出固有的復(fù)雜性,支持多種瀏覽器,設(shè)備和網(wǎng)絡(luò)的實(shí)時(shí)數(shù)據(jù)交換。
Engine.io使用了 WebSocket 和 XMLHttprequest(或JSONP) 封裝了一套自己的 Socket 協(xié)議(暫時(shí)叫 EIO Socket),在低版本瀏覽器里面使用長(zhǎng)輪詢(xún)替代 WebSocket。一個(gè)完整的 EIO Socket 包括多個(gè) XHR 和 WebSocket 連接.
下面從前后端的實(shí)現(xiàn)原理上來(lái)說(shuō)明;
前端
EIO Socket 通過(guò)一個(gè) XHR (XMLHttprequest) 握手。前端發(fā)送一個(gè) XHR,告訴服務(wù)端我要開(kāi)始 XHR 長(zhǎng)輪詢(xún)了。后端返回的數(shù)據(jù)里面包括一個(gè) open 標(biāo)志(數(shù)字 0 表示), 以及一個(gè) sid 、 upgrades 、pingInterval、pingTimeout四個(gè)字段;
sid
sid 是本次 EIO Socket 的會(huì)話 ID,因?yàn)橐淮?EIO Socket 包含了多個(gè)請(qǐng)求,而后端又會(huì)同時(shí)連接多個(gè) EIO Socket,sid 的作用就相當(dāng)于 SESSION ID;
upgrades
會(huì)話升級(jí)得字符串,正常情況下是 ['websocket'],表示可以把連接方式從長(zhǎng)輪詢(xún)升級(jí)到 WebSocket.
pingInterval
設(shè)定每隔在一定時(shí)間發(fā)送一個(gè)ping包,可以用于心跳包的設(shè)置。默認(rèn)為25000
pingTimeout
Server配置的ping超時(shí)時(shí)間,默認(rèn)60000
前端在發(fā)送第一個(gè) XHR 的時(shí)候就開(kāi)始了 XHR 長(zhǎng)輪詢(xún),這個(gè)時(shí)候如果有收發(fā)數(shù)據(jù)的需求,是通過(guò)長(zhǎng)輪詢(xún)實(shí)現(xiàn)的。所謂長(zhǎng)輪詢(xún),是指前端發(fā)送一個(gè) request,服務(wù)端會(huì)等到有數(shù)據(jù)需要返回時(shí)再 response. 前端收到 response 后馬上發(fā)送下一次 request。這樣就可以實(shí)現(xiàn)雙向通信。
前端收到握手的 upgrades 后,EIO 會(huì)檢測(cè)瀏覽器是否支持 WebSocket,如果支持,就會(huì)啟動(dòng)一個(gè) WebSocket 連接,然后通過(guò)這個(gè) WebSocket 往服務(wù)器發(fā)一條內(nèi)容為 probe, 類(lèi)型為 ping 的數(shù)據(jù)。如果這時(shí)服務(wù)器返回了內(nèi)容為 probe, 類(lèi)型為 pong 的數(shù)據(jù),前端就會(huì)把前面建立的 HTTP 長(zhǎng)輪詢(xún)停掉,后面只使用 WebSocket 通道進(jìn)行收發(fā)數(shù)據(jù)。
EIO Socket 生命周期內(nèi),會(huì)間隔一段時(shí)間 (默認(rèn)25000毫秒)ping - pong 一次,用來(lái)測(cè)試網(wǎng)絡(luò)是否正常;
下圖是WebSocket 幀的結(jié)構(gòu)
綠色是發(fā)送,白色是接收。前面的數(shù)字是數(shù)據(jù)包類(lèi)型,2 是 ping, 3 是 pong, 4 是 message.服務(wù)端
服務(wù)端使用 ws 庫(kù)實(shí)現(xiàn) WebSocket 協(xié)議。Socket.io服務(wù)啟動(dòng)時(shí),會(huì)先啟動(dòng)一個(gè) ws 服務(wù)。Socket.io 會(huì)監(jiān)聽(tīng) HTTP 服務(wù)器的 upgrade 和 request 事件。當(dāng) upgrade 事件觸發(fā)時(shí),說(shuō)明可能是 WebSocket 握手,先簡(jiǎn)單校驗(yàn)下,然后把請(qǐng)求交給 ws 服務(wù)進(jìn)行處理,拿到 WebSocket 對(duì)象。當(dāng) request 事件觸發(fā)時(shí),根據(jù) url 路徑判斷是不是 Socket.io的 XHR 請(qǐng)求,拿到 res 和 res 對(duì)象。這樣就可以正確接收和返回客戶(hù)端數(shù)據(jù)了,具體處理過(guò)程和前端部分是對(duì)應(yīng)的。
更多專(zhuān)業(yè)前端知識(shí),請(qǐng)上 【猿2048】www.mk2048.com
總結(jié)
以上是生活随笔為你收集整理的Socket.io 深入理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于ES6的Promise
- 下一篇: js操作table中tr的顺序,实现上移