自從HTML5出來以后,使用WebSocket通信就變得火熱起來,基于WebSocket開發的手機APP和手機游戲也越來越多。我的一些開發APP的朋友,開始使用WebSocket通信,后來覺得通信不夠安全,想要對通信進行加密,于是自然而然地就想從ws升級到wss。在升級的過程中,就會存在舊的ws客戶端與新的wss客戶端同時連接到同一個服務器的情況。所以,如果同一個服務端,能同時支持ws和wss,那就太方便了。
一. 實現方案
但是,要服務端同時支持ws與wss并不太容易,其難點主要在于:wss通道必須在TCP連接剛建立時(收發消息前)就要先進行SSL加密,否則,后續的通信將無法正常進行。如此一來,當同時存在ws和wss客戶端時,服務器在尚未通信之前就無法具體分辨哪個是ws哪個是wss。那怎么辦了?我們的解決方案,是采用試探法,該方案已經在 ESFramework 通信框架中實現。
(1)由于wss通道必須在TCP連接剛建立時(收發消息前)就要先進行SSL加密,否則,后續的通信將無法正常進行。
(2)基于(1),在沒有收發任何消息時,服務端就無法將wss客戶端與其它客戶端區分開來。
(3)為此采用的辦法是:對于任何剛建立的TCP連接,先都不加密它,等收到的第一個消息來判斷其消息的頭標志。
(4)如果頭標志不是ESFramework所規定的標志,則表示這第一個消息是密文,無法被解析,從而說明這個客戶端是wss。于是將該客戶端的ip放到cache中,并斷開該連接。
(5)wss客戶端會重新連上來,此時服務端從cache中發現已經存在目標ip,則判定其為wss客戶端,于是立即使用SSL加密該通道,之后,該wss客戶端就可以正常通信了。
(6)由于wss 客戶端 IP在cache中的過期時間是 6秒左右,所以,如果一個客戶端IP剛登錄了wss客戶端,那么在同一個IP上登錄第二個客戶端(任何客戶端類型),就需要相隔6秒之后。
基于以上方案實現服務端后,我們接下來基于 ESFramework入門demo 來具體講解一下如何在實際應用中同時支持ws和wss。
二. 服務端實現
1. 數字證書
為測試方便,我們可以使用 CertificateCreator 制作一個用于本地測試的數字證書。
運行 CertificateCreator.exe, 然后輸入Common Name(比如Test)、密碼、保存路徑(比如D:\server.pfx),我們就可以得到包含私鑰的證書server.pfx 。雙擊server.pfx ,即可安裝證書。
2. 服務端引擎設置
在服務端RapidServerEngine初始化之前,添加如下代碼設置其 WssOptions 屬性:
WssOptions wssOptions = new WssOptions( new X509Certificate2("D:\\server.pfx", "password") ,SslProtocols.Default ,false); rapidServerEngine.WssOptions = wssOptions;
設置完成后,啟動服務端。
三. 客戶端實現
1. 信任測試用的數字證書
由于上述生成的數字證書僅僅是用于測試的,而是不被正式認可的,所以,需要在瀏覽器設置中,將目標數字證書加入到信任列表。
比如,在360瀏覽器中,可如下設置:
在FireFox中,設置如下:
將服務器的地址(https://127.0.0.1:4530)添加到例外中。
2. 客戶端引擎設置
打開入門demo的Web端源碼中的index.js文件,找到engine的Initialize方法,將 useWss 參數由false修改為true。
然后將Web端的 index.html 文件拖入瀏覽器中運行即可。
四. 運行效果
登錄一個wss客戶端,一個ws客戶端和一個.NET客戶端,服務端的UI顯示如下:
下載 Demo源碼 。
文章列表