天天看點

netty系列之:使用netty搭建websocket伺服器

​​簡介​​

​​netty中的websocket​​

websocket的版本

framedecoder和frameencoder

websocketserverhandshaker

websocketframe

​​netty中使用websocket​​

​​總結​​

簡介

websocket是一個優秀的協定,它是建立在tcp基礎之上的,相容http的網絡協定。通過websocket我們可以實作用戶端和伺服器端的即時通訊,免除了用戶端多次輪循帶來的性能損耗。

既然websocket這麼優秀,那麼怎麼在netty中使用websocket呢?

netty中的websocket

雖然websocket是一個單獨的和http協定完全不同的協定,但是在netty中還是将其放到了http包中。我們回想一下netty中對于各種協定的支援。如果要支援這種協定,肯定需要一個decoder和encoder編碼和解碼器用于對協定進行編解碼。将傳輸的資料從bytebuf轉換到協定類型,或者将協定類型轉換成為bytebuf。

這是netty的工作核心原理,也是後續自定義netty擴充的基礎。

那麼對于websocket來說,是怎麼樣的呢?

websocket作為一種協定,自然不是憑空而來的,通過不斷的發展才到了今天的websocket協定。具體的websocket的發展史我們就不去深究了。我們先看下netty提供的各種websocket的版本。

在websocketversion類中,我們可以看到:

websocketversion是一個枚舉類型,它裡面定義了websocket的4個版本,除了unknown之外,我們可以看到websocket的版本有0,7,8,13這幾個。

我們知道websocket的消息是通過frame來傳遞的,因為不同websocket的版本影響到的是frame的格式的不同。是以我們需要不同的framedecoder和frameencoder來在websocketframe和bytebuf之間進行轉換。

既然websocket有四個版本,那麼相對應的就有4個版本的decoder和encoder:

至于每個版本之間的frame有什麼差別,我們這裡就不細講了,感興趣的朋友可以關注我的後續文章。

熟悉netty的朋友應該都知道,不管是encoder還是decoder都是作用在channel中對消息進行轉換的。那麼在netty中對websocket的支援是怎麼樣的呢?

netty提供了一個websocketserverhandshaker類來統一使用encoder和decoder的使用。netty提供一個工廠類websocketserverhandshakerfactory根據用戶端請求header的websocket版本不同,來傳回不同的websocketserverhandshaker。

同樣的, 我們可以看到,netty為websocket也定義了4種不同的websocketserverhandshaker。

websocketserverhandshaker中定義了handleshake方法,通過傳入channel,并向其添加encoder和decoder

而添加的這兩個newwebsocketencoder和newwebsocketdecoder就是各個websocketserverhandshaker的具體實作中定義的。

所有的ecode和decode都是在websocketframe和bytebuf中進行轉換。websocketframe繼承自defaultbytebufholder,表示它是一個bytebuf的容器。除了儲存有bytebuf之外,它還有兩個額外的屬性,分别是finalfragment和rsv。

finalfragment表示該frame是不是最後一個frame。對于大資料量的消息來說,會将消息拆分成為不同的frame,這個屬性特别有用。

我們再看一下websocket協定消息的格式:

rsv代表的是消息中的擴充字段,也就是rsv1,rsv2和rsv3。

除此之外就是bytebuf的一些基本操作了。

websocketframe是一個抽象類,它的具體實作類有下面幾種:

binarywebsocketframe和textwebsocketframe很好了解,他們代表消息傳輸的兩種方式。

closewebsocketframe是代表關閉連接配接的frame。continuationwebsocketframe表示消息中多于一個frame的表示。

而pingwebsocketframe和pongwebsocketframe是兩個特殊的frame,他們主要用來做伺服器和用戶端的探測。

這些frame都是跟websocket的消息類型一一對應的,了解了websocket的消息類型,對應了解這些frame類還是很有幫助的。

netty中使用websocket

講了這麼多websocket的原理和實作類,接下來就是實戰了。

在這個例子中,我們使用netty建立一個websocket server,然後使用浏覽器用戶端來對server進行通路。

建立websocket server和普通netty伺服器的過程沒有什麼兩樣。隻是在channelpipeline中,需要加入自定義的websocketserverhandler:

這個websocketserverhandler需要做什麼事情呢?

它需要同時處理普通的http請求和websocket請求。

這兩種請求可以通過接收到的msg類型的不同來進行判斷:

在用戶端進行websocket連接配接之前,需要借用目前的channel通道,開啟handleshake:

我們得到handshaker之後,就可以對後續的websocketframe進行處理:

這裡我們隻是機械的傳回消息,大家可以根據自己業務邏輯的不同,對消息進行解析。

有了伺服器端,用戶端該怎麼連接配接呢?很簡單首選構造websocket對象,然後處理各種回調即可:

總結

以上就是使用netty搭建websocket伺服器的完整流程,本文中的伺服器可以同時處理普通http請求和websocket請求,但是稍顯複雜,有沒有更加簡單的方式呢?敬請期待​

公衆号:程式那些事