萬琪偉,盧成林
(南昌工程學院瑤湖學院,江西 南昌 330099)
目前,互聯(lián)網市場的在線通信技術大多仍為傳統(tǒng)的TCP通信協(xié)議,而WebSocket方興未艾,更能適應現(xiàn)代社會發(fā)展的通信需要。本設計應用該技術設計搭建網絡聊天室,彌補了傳統(tǒng)通信的一些缺點,給現(xiàn)代通信架構的設計提供樣本參考。
(1)客戶端自由連接,自由發(fā)言;
(2)完備的文件轉碼機制,使聊天室支持多類型文件的收發(fā)和多狀態(tài)信息的傳輸;
(3)提供統(tǒng)一處理機制,對外提供開放接口,方便開發(fā)部署應用;
(4)并行異步處理模式,提高并行處理時的效率,構建更穩(wěn)定的通信應用。
最早的HTTP網絡傳輸協(xié)議是HTTP0.9,于1991年發(fā)布。它在網絡傳輸過程中只傳輸文本內容,沒有緩存、身份驗證和錯誤機制。由于傳輸前沒有身份驗證機制,所以其傳輸?shù)膬热莶话踩?,有許多方法可以冒充接收方截下這段內容。因此,在該協(xié)議的背景下,個人網站和企業(yè)網站的首頁等一類不需要加密的業(yè)務內容應運而生。由于私密內容不適合在網絡之間傳輸,因此為了提供更多的安全性,身份驗證和錯誤狀態(tài)機制被添加進HTTP1.0。1992年后,互聯(lián)網發(fā)展迎來了第一個巔峰,各種網絡技術應用層出不窮,但網絡間的數(shù)據(jù)傳輸還是基于HTTP1.0協(xié)議,通信技術的更新使得傳輸速度越來越快,數(shù)據(jù)流量越來越大。而HTTP1.0的身份驗證是一次性驗證,對于頻繁的網絡請求,身份驗證占據(jù)的帶寬相當可觀。于是,HTTP1.1在1997年發(fā)布,該協(xié)議一次驗證之后可以進行多次連接。網速的提高使得通過網絡傳輸?shù)奈募热菰絹碓酱螅缫曨l、音頻、鏡像等壓縮文件。原先的一般處理是將大文件分割成小文件傳輸,最后再合并回大文件,使得文件傳輸復雜,小文件也可能發(fā)生丟失,導致傳輸?shù)膬热莶煌暾?。因此,第二代通信技術HTTP2.0為大文件的傳輸提供了更加完美的解決方案[1]。
WebSocket協(xié)議支持發(fā)布于2013年,在(在受控環(huán)境中運行不受信任的代碼的)客戶端與(選擇加入該代碼的通信的)遠程主機之間進行全雙工通信。用于此的安全模型是Web瀏覽器常用的基于原始的安全模式。協(xié)議包括一個開放的握手和隨后的TCP層上的消息幀。該技術的目標是為基于瀏覽器的需要和服務器進行雙向通信的(服務器不能依賴于打開多個HTTP連接(如使用XMLHttpRequest、<iframe>和長輪詢)應用程序提供一種通信機制。簡單地說,WebSocket協(xié)議之前,雙向通信是通過不停發(fā)送HTTP請求從服務器拉取更新來實現(xiàn),導致效率低下,而WebSocket協(xié)議能較好地解決此類問題。
實現(xiàn)WebSocket連線過程中,需要通過瀏覽器發(fā)出WebSocket連線請求,然后服務器發(fā)出回應,這個過程通常稱為“握手”。在WebSocket API,瀏覽器和服務器只需要做一個握手的動作,瀏覽器和服務器之間就形成了一條快速通道。兩者之間可以直接進行數(shù)據(jù)的互相傳送。在WebSocket協(xié)議中,實現(xiàn)即時服務有兩大好處。
(1)Header容量小
相互溝通的Header很小,大概只有2 Bytes。
(2)Server Push提供主動推送服務
服務器的推送。服務器不再被動接收瀏覽器的請求后才返回數(shù)據(jù),而是在有新數(shù)據(jù)時就主動推送給瀏覽器。
瀏覽器發(fā)送的Header
GET/webfin/websocket/HTTP/1.1
Host:localhost
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Key:xqBt3ImNzJbYqRINx EFlkg==
Origin:http://服務器地址
Sec-WebSocket-Version:13
服務器回應Header
HTTP/1.1 101 Switching Protocols
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Accept:K7DJLdLooIwIG/MOpvWFB3y3FE8=
傳統(tǒng)的HTTP協(xié)議是無狀態(tài)的,每次請求(Request)都要由客戶端(如瀏覽器)主動發(fā)起,服務端進行處理后返回response結果,而服務端很難主動向客戶端發(fā)送數(shù)據(jù)。對于信息變化不頻繁的Web應用來說,它造成的麻煩較小,而對于涉及實時信息的Web應用卻帶來了很大不便,如帶有即時通信、實時數(shù)據(jù)、訂閱推送等功能的應用。在WebSocket規(guī)范提出前,開發(fā)人員若要實現(xiàn)這些實時性較強的功能,經常會使用折中的解決方法:輪詢(Polling)和Comet技術。其實,Comet技術本質上也是一種輪詢,是一種改進的輪詢[2]。
記S1為傳統(tǒng)的HTTP協(xié)議規(guī)則(以下簡稱TCP),S2為基于HTTP1.1的WebSocket協(xié)議規(guī)則(以下簡稱WS)。
使用WS有以下幾點優(yōu)勢:
(1)建立在TCP協(xié)議之上。
(2)與HTTP協(xié)議有著良好的兼容性。默認端口也是80和443,握手階段采用HTTP協(xié)議。因此,握手時不容易屏蔽,能通過各種HTTP代理服務器。
(3)數(shù)據(jù)格式比較輕量,性能開銷小,通信高效。
(4)可以發(fā)送文本,也可以發(fā)送二進制數(shù)據(jù)。
(5)沒有同源限制,客戶端可以與任意服務器通信。
(6)協(xié)議標識符是ws(如果加密,則為wss),服務器網址就是URL。
正如自然界中有“物競天擇,適者生存”,一代又一代的通信協(xié)議被提出,隨著時代的發(fā)展又不斷淘汰。技術的產生和需求是分不開的。根據(jù)社會對即時通信協(xié)議的需求,基于對上述可行性的分析,基于HTTP1.1的WebSocket協(xié)議的新式網絡聊天室的開發(fā)設計是一種較合理的選擇。
相比于傳統(tǒng)TCP協(xié)議核心,服務器端增加了一個HTTPRequest的Context連接池。在有客戶端連接請求時,將正確請求壓入Dictionary中實現(xiàn)了長輪詢和有狀態(tài)的雙向連接。新建線程監(jiān)聽此端口或者在有服務器消息后主動向客戶端推送消息,調用Dictionary鍵值對找出客戶端口,同時使用.NET提供的WebSocket.State屬性判斷客戶端是否在線,以實現(xiàn)實時雙工通信和離線消息保持處理。
另外,WebSocket的核心相比于TCP有更大的可設計性:
(1)可設計多樣化網絡核心存在形式?;?NET,WebSocket可以部署為控制臺,可以部署為Windows窗口程序,可以部署為ASP網站處理程序。在MicroSoft發(fā)布了最新技術規(guī)范.NET Core后,作為新式的更完美的通信技術,可以部署在支持.NET框架的任何平臺。
(2)可設計安全連接和狀態(tài)連接。WebSocket可以通過加載SSL證書應用世界主流的數(shù)據(jù)通信加密協(xié)議來保護傳輸數(shù)據(jù)。一次握手可以保持連接狀態(tài),節(jié)約帶寬和性能。
目前主流的瀏覽器核心均支持WebSocket通信協(xié)議,W3C為客戶端規(guī)定了更加簡潔高效的連接處理API,使得客戶端的設計可以更簡約和方便。
開發(fā)平臺CodeVS語言JavaScript
Window.ws=newWebSocket(‘wss://forexample.com/Handler1.ashx?user=’+$(“#user”).val());
服務器端的通信中轉是此次研究的核心,也是此次技術的難點。利用新技術更新傳統(tǒng)技術,并修復已知問題使它更符合現(xiàn)代社會需要,需要我們不斷嘗試和研究,不斷更新迭代技術開發(fā)出更加高效和完備的通信體系[3-4]。
圖1表述了協(xié)議數(shù)據(jù)從設計物理層生成,經過鏈路處理,使用網絡協(xié)議進行修飾,最后通過套接字接口傳達到應用層的過程。簡言之,應用層為消息池,儲存消息為Server和Client所用。
圖1 協(xié)議內容
圖2 表明服務運行時,服務器專用線程監(jiān)聽某個應用層端口的連接,然后接受連接請求和驗證連接協(xié)議。成功后,在客戶端對應用層進行消息傳遞前,服務器的recv()保持阻塞狀態(tài),send()保持接受外部影響的激活狀態(tài)。在每一次輪詢結束后,recv()重新阻塞,send()時刻活躍,并對服務器和客戶端改動做出回應,實現(xiàn)異步模式。
圖2 雙工協(xié)議流程
整個平臺由服務器端和客戶端組成。服務器端用來處理各個客戶端發(fā)來的數(shù)據(jù)(聊天消息)和向客戶端分發(fā)聊天消息記錄。每一個聊天室需新建一個類。
此類需包含以下組件。(1)房間號:用來顯示表示房間ID的字符串組成的標識符。(2)成員:應使用動態(tài)數(shù)組或者可變長度的堆棧,如果實現(xiàn)1對1聊天室,把成員數(shù)量限制為2即可。(3)端口號:服務器上描述房間位置的唯一標識符,用以封裝IPv4對外接口和客戶端連接服務端的端點。(4)消息結構:成員用戶IP地址(識別單個用戶)、發(fā)送消息的時間、發(fā)送的消息內容和其他DIY描述(如個性簽名、頭像等)。(5)成員列表:儲存所有的在線成員,可選添加聊天室管理員。(6)綁定的數(shù)據(jù)庫:將每一條消息結構存入數(shù)據(jù)庫,便于隨時調出查看。
至少包含如下方法。(1)獲取歷史聊天記錄。(2)輸出成員列表:獲取在線人數(shù),根據(jù)已連接的IP地址定義單個成員。(3)獲取客戶端消息:將消息結構存入數(shù)據(jù)庫,向所有本房間的客戶端推送消息。(4)創(chuàng)建WebSocket服務器端監(jiān)聽服務:基于WebSocket協(xié)議的互聯(lián)機制,可以保持客戶端在線,同時監(jiān)聽客戶端狀態(tài),做到身份驗證和消息加密的安全保障,且能夠在有成員的狀態(tài)下活躍,無成員時靜默,最大程度節(jié)約服務器資源和帶寬。(5)關閉WebSocket服務:節(jié)省內存。
服務器類需包括以下組件。(1)聊天室列表棧:儲存和提取各聊天室信息。(2)聊天室工廠類:批量規(guī)范地創(chuàng)建聊天室,將聊天室壓入聊天室列表Stack中。(3)WebSocket服務:向每一個客戶端發(fā)送房間列表或創(chuàng)建房間信息或其他內容。(4)其他功能,如多線程支持、日志記錄、錯誤列表。
客戶端需包括以下功能。(1)WebSocketClient:WebSocket服務客戶端,用于連接服務器進行網絡通信協(xié)議,使用WebSocket協(xié)議的客戶端口和連接基礎。(2)消息處理組件:能夠對即將發(fā)送的消息文本處理,或者對即將發(fā)送的圖片和文件適當編碼,使之能用ws協(xié)議傳輸。處理服務器返回的消息,使之能正常且正確地顯示在客戶端。(3)聊天室接口:獲取聊天室和成員信息,管理聊天室連接,生成聊天室Stack使客戶端能加入多個聊天室。(4)其他功能,如日志記錄、錯誤列表。
聊天室包含的主要算法如下。
開發(fā)環(huán)境:CodeVS,語言JavaScript
(1)圖片轉base:64算法
function getBase64Image(img){
var base64, base;
var canvas = document.createElement(“canvas”);
canvas.width=img.width;
canvas.height=img.height;
var ctx=canvas.getContext(“2d”);
ctx.drawImage(img,0,0,img.width,img.height);
base=canvas.toDataURL(“image/png”);
base64 = base.toString().substr(base.toString().indexOf(“,”)+1);
return base64;
}
(2)小文檔壓縮二進制算法
該算法可選支持,具體取決于對消息的支持程度。
(3)SHA1算法
function count(SecWebSocketKey){
if(!(SecWebSocketKey==””)){
var shaObj=newjsSHA(“SHA1”,”TEXT”,{“n umRounds”:1});
shaObj.update(SecWebSocketKey+”258EAFA5-E914-47DA-95CA-C5AB0DC85B11”);
return shaObj.getHash(“B64”);
else return -1;
}
可安裝SSL證書,以安全化雙工連接。
本設計中服務器和客戶端的結構清晰,條理鮮明,且完整地基于WebSocket協(xié)議的使用及拓展,服務器及客戶端都擁有獨立的工作形式,跨越了兩個平臺。該研究應用范圍不僅適用于小型局域互聯(lián)網絡建設,隨著社會對即時通信需求的與日劇增,可延伸至其他領域。