天天看點

學習 NodeJS 第八天:Socket 通訊

一般來講,HTTP 是基于文本的“單向”通訊機制。這裡所謂的“單向”,乃相對于“雙向”而言,因為 HTTP 伺服器隻需根據請求返還恰當的 HTML 給用戶端即可,不涉及用戶端向服務端的通訊。這種單向的機制比較簡單,對網絡品質要求也不高。而更多的場景則是需要可靠、穩定的端到端連接配接。一般這種服務是實時的、有态的而且是長連接配接,長連接配接則暗示兩段須達緻相向通訊的能力,也就說是服務端用戶端兩者間能夠實時地互相間通信。毫無疑問,能夠實時通信的伺服器正是我們對伺服器基本要求之一。差別于 HTTP 伺服器以 HTTP 為通訊協定, 實時伺服器一般采用較為底層的 TCP/IP 為協定通訊,實作了“套位元組 Socket”的雙向機制。

Socket 是根據博克萊 (U.C.Berkley) 大學早期發展的 Socket 概念寫成的,其設計理念是是将網絡傳輸類比成檔案的讀取與寫入 (傳送的動作被視為是寫入/接收的動作被視為是讀取),如此、傳送與接收就簡化為程式設計人員比較容易懂的 讀取與寫入,降低了網絡程式設計的學習困難度。

聊天室的實時連接配接基于底層的 TCP 直接連接配接,為此我們須調用 Node 的 TCP 子產品。如果不太熟悉所謂 TCP 網絡程式設計?太底層了是不是?沒關系,我也不熟悉,邊學邊做嘛,隻不過千萬不必因為遇到陌生的詞彙而害怕,其實這樣原理并不深奧,而且下面的例子也十分的簡單易懂!咱們就從最簡單的開始吧,下面代碼僅僅十行,它的作用是伺服器向用戶端輸出一段文本,完成 Sever --> Client 的單向通訊。

用戶端可以是系統自帶的 Telnet:

執行 telnet 後,與服務點連接配接,回報 Hi! Bye! 的字元,并立刻結束服務端程式終止連接配接。如果我們要服務端接到到用戶端的資訊?可以監聽 server.data 事件并且不要中止連接配接(否則會立刻結束無法接受來自用戶端的消息):

這裡要說明一下的是,不不同作業系統對端口範圍的限制不一樣,有可能是随機的。

那麼上面是不是一個完整功能的代碼呢?我們說還有一個問題沒有考慮進去:那就是一旦某個用戶端退出,卻仍保留在 clientList 裡面,這明顯是一個空指針(NullPoint)。如果是在這樣的話我們寫程式太脆弱了,能不能更健壯一些?——請接着看。

首先我們簡單地把 client 從數組 clientList 中移除掉。完成這工作一點都不困難。Node TCP API 已經為我們提供了 end 事件,即用戶端中止與服務端連接配接的時候發生。移除 client 對象的代碼如下:

但是我們還不敢說上述代碼很健壯,因為一旦 end 沒有被觸發,異常仍然存在着。下面我們看看解決之道:重寫 broadcast():

TCP API 中還提供一個 error 事件,用于捕捉用戶端的異常:

Node 網絡程式設計的 API 還豐富,此次僅僅是個入門,更多的内容請接着看,關于浏覽器 Socket 應用。

前面說到,浏覽器雖然也屬于用戶端的一種,但僅支援“單工”的 HTTP 通訊。有見及此,HTML5 新規範中推出了基于浏覽器的 WebSocket,開發了底層的接口,允許我們能進行 更強大的操作,超越以往的 XHR。

如第一個例子那般,我們無須第三方架構就可以直接與 Node TCP 伺服器 進行 Socket  通訊。

WebSocket

Socket over Flash API

XHR Polling 長連接配接

XHR Multipart Streaming

Forever Iframe

JSONP Polling

經過封裝,我們可以不探究用戶端使用上述哪一種技術達緻“全雙工”;而我們編寫代碼時,亦無論考慮哪種放法,因為 Socket.IO 給我們的 API 隻有一套。了解 Socket.IO 其用法就可以了。

先在浏覽器部署 Socket.IO 的前端代碼:

服務端 Node 代碼:

當用戶端連接配接時,服務端會同時出發兩個事件:server.onRequest 和 Socket.onConnection。它們之間有什麼差別呢?差別在于 Socket 的是持久性的。

多個 Socket 連接配接,先是用戶端代碼:

服務端代碼:

如上代碼,我們可以劃分多個命名空間,分别是 upandrunning 和 weather。

關于 Express 中使用 Soclet.io,可以參考《Node:Up and Ruuning》一書的 7.2.2 小節。

今晚時間的關系,涉及 Socket.io 許多方面還沒有談,容小弟我日後再了解。

繼續閱讀