最近在作項目優化工做時,用到了Socket.io , Socket.io 文檔比較少, 結合官網介紹以及本身在項目開發中的摸索,總結以下內容;前端
Socket.io將Websocket和輪詢 (Polling)機制以及其它的實時通訊方式封裝成了通用的接口,而且在服務端實現了這些實時機制的相應代碼。也就是說,Websocket僅僅是Socket.io實現實時通訊的一個子集;web
Socket.io 支持以下方式的通訊方式,根據瀏覽器的支持程度,自動選擇使用哪一種技術進行通訊:後端
Socket.io 底層是 Engine.io; Engine.io做爲Socket.io的服務器和瀏覽器之間交換的數據的傳輸層,實現了跨平臺的雙向通訊。可是它不會取代Socket.io,它只是抽象出固有的複雜性,支持多種瀏覽器,設備和網絡的實時數據交換。瀏覽器
Engine.io使用了 WebSocket 和 XMLHttprequest(或JSONP) 封裝了一套本身的 Socket 協議(暫時叫 EIO Socket),在低版本瀏覽器裏面使用長輪詢替代 WebSocket。一個完整的 EIO Socket 包括多個 XHR 和 WebSocket 鏈接.服務器
下面從先後端的實現原理上來講明;websocket
EIO Socket 經過一個 XHR (XMLHttprequest) 握手。前端發送一個 XHR,告訴服務端我要開始 XHR 長輪詢了。後端返回的數據裏面包括一個 open 標誌(數字 0 表示), 以及一個 sid 、 upgrades 、pingInterval、pingTimeout四個字段;網絡
sid 是本次 EIO Socket 的會話 ID,由於一次 EIO Socket 包含了多個請求,然後端又會同時鏈接多個 EIO Socket,sid 的做用就至關於 SESSION ID;socket
會話升級得字符串,正常狀況下是 ['websocket'],表示能夠把鏈接方式從長輪詢升級到 WebSocket.測試
設定每隔在必定時間發送一個ping包,能夠用於心跳包的設置。默認爲25000優化
Server配置的ping超時時間,默認60000
前端在發送第一個 XHR 的時候就開始了 XHR 長輪詢,這個時候若是有收發數據的需求,是經過長輪詢實現的。所謂長輪詢,是指前端發送一個 request,服務端會等到有數據須要返回時再 response. 前端收到 response 後立刻發送下一次 request。這樣就能夠實現雙向通訊。
前端收到握手的 upgrades 後,EIO 會檢測瀏覽器是否支持 WebSocket,若是支持,就會啓動一個 WebSocket 鏈接,而後經過這個 WebSocket 往服務器發一條內容爲 probe, 類型爲 ping 的數據。若是這時服務器返回了內容爲 probe, 類型爲 pong 的數據,前端就會把前面創建的 HTTP 長輪詢停掉,後面只使用 WebSocket 通道進行收發數據。
EIO Socket 生命週期內,會間隔一段時間 (默認25000毫秒)ping - pong 一次,用來測試網絡是否正常;
下圖是WebSocket 幀的結構
服務端使用 ws 庫實現 WebSocket 協議。Socket.io服務啓動時,會先啓動一個 ws 服務。Socket.io 會監聽 HTTP 服務器的 upgrade 和 request 事件。當 upgrade 事件觸發時,說明多是 WebSocket 握手,先簡單校驗下,而後把請求交給 ws 服務進行處理,拿到 WebSocket 對象。當 request 事件觸發時,根據 url 路徑判斷是否是 Socket.io的 XHR 請求,拿到 res 和 res 對象。這樣就能夠正確接收和返回客戶端數據了,具體處理過程和前端部分是對應的。