【筆記】Socket,Websocket,Socket.io的差異

31 7月, 2018

【筆記】Socket,Websocket,Socket.io的差異





最近因為需求碰到需要用socket.io去做介接,
從而也好好的釐清長久以來的困惑。
Socket,Websocket,Socket.io,
這幾個連線通訊用的東西到底是怎樣的層級劃分。

依據七層協議的優先順序

排列應該是 socket,websocket,scoket.io

(一)Socket

Socket簡單來說,就是以前的TCP/IP
實現繁瑣且困難,
後來有人封裝成一個簡易的介面來讓開發人員使用。
現在也變成通訊的標準之一。

有的人會把它定義在「傳輸層」,
也有的人定義在「傳輸層跟應用層之間」。
就我個人的理解,它應該是在後者比較正確。

Socket大部分傳輸方式為stream 
傳輸的載體類型為binary
在解析包體上通常都需要處理「黏包

由於它是一個通訊介面,
所以包體的通訊協議怎麼定義,如何定義叫做「一包」
各家做法都不太一樣。

不過大部分都不脫離以下幾點:
(1)添加「包頭」來定義消息長度
(2)加上「結尾符」

使用注意要點:
(1)需要自訂消息協議
(2)需要處理黏包的問題


(二)Websocket

Websocket,從字面上很容易就能理解。
它是為了提升web通訊速度而被創造出來的一種「協議」
在七層模型中是屬於「應用層」

它的原理是瀏覽器底層使用「socket」當作通訊介面,
通訊協議才是採用它自身的「websocket協議」。

可以想成,溝通的協議跟水管都裝在瀏覽器上
只要瀏覽器有支援,
就可以使用這個協議透過web來跟伺服器做溝通。

在前幾年可能會有很多瀏覽器不支援。
但在現今,瀏覽器的版本都已經趨近成熟,
大部分都支援websocket的協議。

而圖面為什麼有出現Http協議(下圖)


是因為websocket再進行HandShaking的時候。
一開始是使用「Http協議」在進行雙方交握。
等待到雙方交握完後,http協議之後就不會再用到。
之後就是走Websocket的協議。

websocket協議的載體類型有二種:binary或text
但是只能擇其一來使用

而在使用上,由於它協議的特性。
socket「黏包」的問題在這邊獲得了解決。
以「Frame」為單位。

開發者不需要再自己去處理黏包的問題。
websocket已經將每一包變成一個frame來供使用。相當貼心。


使用注意要點:
(1)瀏覽器使用的話,須注意瀏覽器版本是否支持。


(三)Socket.io

Socket.io也是為了解決web即時通訊而誕生的。
但socket.io跟websocket不太一樣,它不屬於通用的協議。
它是一個框架一個類庫。


它要解決的是
當時一些瀏覽器還不支持websocket協議的時候。
socket.io會改選擇使用傳統的long polling(長輪詢)方式運作。
如果支援的話,會升級成websocket的協議。


簡單來說,它是建立在websocket之上的。
不太一樣的是,socket io在做雙向溝通的時候,
可以使用使用可支援的協議來進行溝通。
降低開發人員的處理複雜度,
只需要專心的面向程序介面即可。

而在溝通之間的格式載體,
雖然socket.io是建立在websocket之上。
但是它有它自定義的溝通格式。

在每個Websokcet Frame
都自訂了自己的opcode(操作碼)跟格式內容

所以會有人說websocket跟socket.io無法溝通。
但這其實不是很正確,websokcet比socket.io還底層。
只要websocket實做socket.io的封包協議,
websocket是能夠跟scoket.io進行溝通的。

websocket要連上scoekt.io
只要在host後面加上下面這行參數就可以進行連接。

ws://{IP}:{PORT}/socket.io/?EIO=4&transport=websocket
view raw wsConnect.cs hosted with ❤ by GitHub

(eio代表要使用哪個版本,transport代表要使用的協議)

但是這只是單純的連接,
後續還有心跳包,溝通的格式,也都需要調整。

至於為什麼圖面會有engine.io,
那是因為socket.io的核心其實是engine.io
所有通訊相關,連接等等,
都是engine.io在實現

socket.io本身並沒有任何連線的功能,主要是靠engine.io

而socket.io僅僅是在上層做一些介面封裝
以及封包的格式去做制定。

假設以socket.io的發送封包
this.emit("test",2);
view raw send.js hosted with ❤ by GitHub

封包格式會如下
42["test",2]
view raw packet.js hosted with ❤ by GitHub

第一位「4」代表「Engine.io」的操作碼
第二位「2」代表「Socket.io」的操作碼
後面的資料包裝方式就是Socket.io所制定的。

websocket只要按照socket.io協議方式,
也能夠跟socket.io伺服器溝通。



後記:
即時通訊這麼多選擇,如果是在選擇上。
個人還是比較偏向使用Websocket或是Socket,
Socket.io畢竟還是包裝了太多的東西。

當然還忘了介紹很熱門的WebRTC,
但是由於還沒有時間跟機會去碰觸。
所以就沒有在這筆記上了。














張貼留言