久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

使用 HTML5 WebSocket 構(gòu)建實(shí)時(shí) Web 應(yīng)用

 大芬油畫(huà) 2014-10-20
在 IBM Bluemix 云平臺(tái)上開(kāi)發(fā)并部署您的下一個(gè)應(yīng)用。現(xiàn)在就開(kāi)始免費(fèi)試用

作為下一代的 Web 標(biāo)準(zhǔn),,HTML5 擁有許多引人注目的新特性,,如 Canvas、本地存儲(chǔ),、多媒體編程接口,、WebSocket 等等。這其中有“Web 的 TCP ”之稱(chēng)的 WebSocket 格外吸引開(kāi)發(fā)人員的注意,。WebSocket 的出現(xiàn)使得瀏覽器提供對(duì) Socket 的支持成為可能,從而在瀏覽器和服務(wù)器之間提供了一個(gè)基于 TCP 連接的雙向通道,。Web 開(kāi)發(fā)人員可以非常方便地使用 WebSocket 構(gòu)建實(shí)時(shí) web 應(yīng)用,,開(kāi)發(fā)人員的手中從此又多了一柄神兵利器。本文首先介紹 HTML5 WebSocket 的基本概念以及這個(gè)規(guī)范試圖解決的問(wèn)題,,然后介紹 WebSocket 的基本原理和編程接口,。接下來(lái)會(huì)通過(guò)一個(gè)簡(jiǎn)單案例來(lái)示范怎樣實(shí)現(xiàn)一個(gè) WebSocket 應(yīng)用,并且展示 WebSocket 如何在功能強(qiáng)大和編程簡(jiǎn)單易用上達(dá)到的完美統(tǒng)一,。最后介紹了目前主流瀏覽器對(duì) WebSocket 支持的狀況,、局限性以及未來(lái)的展望。

實(shí)時(shí) Web 應(yīng)用的窘境

Web 應(yīng)用的信息交互過(guò)程通常是客戶(hù)端通過(guò)瀏覽器發(fā)出一個(gè)請(qǐng)求,,服務(wù)器端接收和審核完請(qǐng)求后進(jìn)行處理并返回結(jié)果給客戶(hù)端,,然后客戶(hù)端瀏覽器將信息呈現(xiàn)出來(lái),這種機(jī)制對(duì)于信息變化不是特別頻繁的應(yīng)用尚能相安無(wú)事,,但是對(duì)于那些實(shí)時(shí)要求比較高的應(yīng)用來(lái)說(shuō),,比如說(shuō)在線(xiàn)游戲、在線(xiàn)證券,、設(shè)備監(jiān)控,、新聞在線(xiàn)播報(bào)、RSS 訂閱推送等等,,當(dāng)客戶(hù)端瀏覽器準(zhǔn)備呈現(xiàn)這些信息的時(shí)候,,這些信息在服務(wù)器端可能已經(jīng)過(guò)時(shí)了。所以保持客戶(hù)端和服務(wù)器端的信息同步是實(shí)時(shí) Web 應(yīng)用的關(guān)鍵要素,,對(duì) Web 開(kāi)發(fā)人員來(lái)說(shuō)也是一個(gè)難題,。在 WebSocket 規(guī)范出來(lái)之前,開(kāi)發(fā)人員想實(shí)現(xiàn)這些實(shí)時(shí)的 Web 應(yīng)用,不得不采用一些折衷的方案,,其中最常用的就是輪詢(xún) (Polling) 和 Comet 技術(shù),,而 Comet 技術(shù)實(shí)際上是輪詢(xún)技術(shù)的改進(jìn),又可細(xì)分為兩種實(shí)現(xiàn)方式,,一種是長(zhǎng)輪詢(xún)機(jī)制,,一種稱(chēng)為流技術(shù)。下面我們簡(jiǎn)單介紹一下這幾種技術(shù):

輪詢(xún)

這是最早的一種實(shí)現(xiàn)實(shí)時(shí) Web 應(yīng)用的方案,??蛻?hù)端以一定的時(shí)間間隔向服務(wù)端發(fā)出請(qǐng)求,以頻繁請(qǐng)求的方式來(lái)保持客戶(hù)端和服務(wù)器端的同步,。這種同步方案的最大問(wèn)題是,,當(dāng)客戶(hù)端以固定頻率向服務(wù)器發(fā)起請(qǐng)求的時(shí)候,服務(wù)器端的數(shù)據(jù)可能并沒(méi)有更新,,這樣會(huì)帶來(lái)很多無(wú)謂的網(wǎng)絡(luò)傳輸,,所以這是一種非常低效的實(shí)時(shí)方案。

長(zhǎng)輪詢(xún):

長(zhǎng)輪詢(xún)是對(duì)定時(shí)輪詢(xún)的改進(jìn)和提高,,目地是為了降低無(wú)效的網(wǎng)絡(luò)傳輸,。當(dāng)服務(wù)器端沒(méi)有數(shù)據(jù)更新的時(shí)候,連接會(huì)保持一段時(shí)間周期直到數(shù)據(jù)或狀態(tài)改變或者時(shí)間過(guò)期,,通過(guò)這種機(jī)制來(lái)減少無(wú)效的客戶(hù)端和服務(wù)器間的交互,。當(dāng)然,如果服務(wù)端的數(shù)據(jù)變更非常頻繁的話(huà),,這種機(jī)制和定時(shí)輪詢(xún)比較起來(lái)沒(méi)有本質(zhì)上的性能的提高,。

流:

流技術(shù)方案通常就是在客戶(hù)端的頁(yè)面使用一個(gè)隱藏的窗口向服務(wù)端發(fā)出一個(gè)長(zhǎng)連接的請(qǐng)求。服務(wù)器端接到這個(gè)請(qǐng)求后作出回應(yīng)并不斷更新連接狀態(tài)以保證客戶(hù)端和服務(wù)器端的連接不過(guò)期,。通過(guò)這種機(jī)制可以將服務(wù)器端的信息源源不斷地推向客戶(hù)端,。這種機(jī)制在用戶(hù)體驗(yàn)上有一點(diǎn)問(wèn)題,需要針對(duì)不同的瀏覽器設(shè)計(jì)不同的方案來(lái)改進(jìn)用戶(hù)體驗(yàn),,同時(shí)這種機(jī)制在并發(fā)比較大的情況下,,對(duì)服務(wù)器端的資源是一個(gè)極大的考驗(yàn)。

綜合這幾種方案,,您會(huì)發(fā)現(xiàn)這些目前我們所使用的所謂的實(shí)時(shí)技術(shù)并不是真正的實(shí)時(shí)技術(shù),,它們只是在用 Ajax 方式來(lái)模擬實(shí)時(shí)的效果,在每次客戶(hù)端和服務(wù)器端交互的時(shí)候都是一次 HTTP 的請(qǐng)求和應(yīng)答的過(guò)程,,而每一次的 HTTP 請(qǐng)求和應(yīng)答都帶有完整的 HTTP 頭信息,,這就增加了每次傳輸?shù)臄?shù)據(jù)量,而且這些方案中客戶(hù)端和服務(wù)器端的編程實(shí)現(xiàn)都比較復(fù)雜,,在實(shí)際的應(yīng)用中,,為了模擬比較真實(shí)的實(shí)時(shí)效果,,開(kāi)發(fā)人員往往需要構(gòu)造兩個(gè) HTTP 連接來(lái)模擬客戶(hù)端和服務(wù)器之間的雙向通訊,一個(gè)連接用來(lái)處理客戶(hù)端到服務(wù)器端的數(shù)據(jù)傳輸,,一個(gè)連接用來(lái)處理服務(wù)器端到客戶(hù)端的數(shù)據(jù)傳輸,,這不可避免地增加了編程實(shí)現(xiàn)的復(fù)雜度,也增加了服務(wù)器端的負(fù)載,,制約了應(yīng)用系統(tǒng)的擴(kuò)展性,。

回頁(yè)首

WebSocket 的拯救

HTML5 WebSocket 設(shè)計(jì)出來(lái)的目的就是要取代輪詢(xún)和 Comet 技術(shù),使客戶(hù)端瀏覽器具備像 C/S 架構(gòu)下桌面系統(tǒng)的實(shí)時(shí)通訊能力,。 瀏覽器通過(guò) JavaScript 向服務(wù)器發(fā)出建立 WebSocket 連接的請(qǐng)求,,連接建立以后,客戶(hù)端和服務(wù)器端就可以通過(guò) TCP 連接直接交換數(shù)據(jù),。因?yàn)?WebSocket 連接本質(zhì)上就是一個(gè) TCP 連接,,所以在數(shù)據(jù)傳輸?shù)姆€(wěn)定性和數(shù)據(jù)傳輸量的大小方面,和輪詢(xún)以及 Comet 技術(shù)比較,,具有很大的性能優(yōu)勢(shì),。Websocket.org 網(wǎng)站對(duì)傳統(tǒng)的輪詢(xún)方式和 WebSocket 調(diào)用方式作了一個(gè)詳細(xì)的測(cè)試和比較,將一個(gè)簡(jiǎn)單的 Web 應(yīng)用分別用輪詢(xún)方式和 WebSocket 方式來(lái)實(shí)現(xiàn),,在這里引用一下他們的測(cè)試結(jié)果圖:

圖 1. 輪詢(xún)和 WebSocket 實(shí)現(xiàn)方式的網(wǎng)絡(luò)負(fù)載對(duì)比圖
圖 1. 輪詢(xún)和 WebSocket 實(shí)現(xiàn)方式的網(wǎng)絡(luò)負(fù)載對(duì)比圖

通過(guò)這張圖可以清楚的看出,,在流量和負(fù)載增大的情況下,WebSocket 方案相比傳統(tǒng)的 Ajax 輪詢(xún)方案有極大的性能優(yōu)勢(shì),。這也是為什么我們認(rèn)為 WebSocket 是未來(lái)實(shí)時(shí) Web 應(yīng)用的首選方案的原因。

回頁(yè)首

WebSocket 規(guī)范

WebSocket 協(xié)議本質(zhì)上是一個(gè)基于 TCP 的協(xié)議,。為了建立一個(gè) WebSocket 連接,,客戶(hù)端瀏覽器首先要向服務(wù)器發(fā)起一個(gè) HTTP 請(qǐng)求,這個(gè)請(qǐng)求和通常的 HTTP 請(qǐng)求不同,,包含了一些附加頭信息,,其中附加頭信息”Upgrade: WebSocket”表明這是一個(gè)申請(qǐng)協(xié)議升級(jí)的 HTTP 請(qǐng)求,服務(wù)器端解析這些附加的頭信息然后產(chǎn)生應(yīng)答信息返回給客戶(hù)端,,客戶(hù)端和服務(wù)器端的 WebSocket 連接就建立起來(lái)了,,雙方就可以通過(guò)這個(gè)連接通道自由的傳遞信息,并且這個(gè)連接會(huì)持續(xù)存在直到客戶(hù)端或者服務(wù)器端的某一方主動(dòng)的關(guān)閉連接,。

下面我們來(lái)詳細(xì)介紹一下 WebSocket 規(guī)范,,由于這個(gè)規(guī)范目前還是處于草案階段,版本的變化比較快,,我們選擇 draft-hixie-thewebsocketprotocol-76版本來(lái)描述 WebSocket 協(xié)議,。因?yàn)檫@個(gè)版本目前在一些主流的瀏覽器上比如 Chrome,、FireFox,、Opera 上都得到比較好的支持,,您如果參照的是新一些的版本話(huà),,內(nèi)容可能會(huì)略有差別。

一個(gè)典型的 WebSocket 發(fā)起請(qǐng)求和得到響應(yīng)的例子看起來(lái)如下:

清單 1. WebSocket 握手協(xié)議
客戶(hù)端到服務(wù)端: 
GET /demo HTTP/1.1 
Host:  
Connection: Upgrade 
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 
Upgrade: WebSocket 
Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5 
Origin: http:// 
[8-byte security key] 

服務(wù)端到客戶(hù)端:
HTTP/1.1 101 WebSocket Protocol Handshake 
Upgrade: WebSocket 
Connection: Upgrade 
WebSocket-Origin: http:// 
WebSocket-Location: ws:///demo 
[16-byte hash response]

這些請(qǐng)求和通常的 HTTP 請(qǐng)求很相似,,但是其中有些內(nèi)容是和 WebSocket 協(xié)議密切相關(guān)的,。我們需要簡(jiǎn)單介紹一下這些請(qǐng)求和應(yīng)答信息,”Upgrade:WebSocket”表示這是一個(gè)特殊的 HTTP 請(qǐng)求,,請(qǐng)求的目的就是要將客戶(hù)端和服務(wù)器端的通訊協(xié)議從 HTTP 協(xié)議升級(jí)到 WebSocket 協(xié)議,。從客戶(hù)端到服務(wù)器端請(qǐng)求的信息里包含有”Sec-WebSocket-Key1”、“Sec-WebSocket-Key2”和”[8-byte securitykey]”這樣的頭信息,。這是客戶(hù)端瀏覽器需要向服務(wù)器端提供的握手信息,,服務(wù)器端解析這些頭信息,并在握手的過(guò)程中依據(jù)這些信息生成一個(gè) 16 位的安全密鑰并返回給客戶(hù)端,,以表明服務(wù)器端獲取了客戶(hù)端的請(qǐng)求,,同意創(chuàng)建 WebSocket 連接。一旦連接建立,,客戶(hù)端和服務(wù)器端就可以通過(guò)這個(gè)通道雙向傳輸數(shù)據(jù)了,。

在實(shí)際的開(kāi)發(fā)過(guò)程中,為了使用 WebSocket 接口構(gòu)建 Web 應(yīng)用,,我們首先需要構(gòu)建一個(gè)實(shí)現(xiàn)了 WebSocket 規(guī)范的服務(wù)器,,服務(wù)器端的實(shí)現(xiàn)不受平臺(tái)和開(kāi)發(fā)語(yǔ)言的限制,只需要遵從 WebSocket 規(guī)范即可,,目前已經(jīng)出現(xiàn)了一些比較成熟的 WebSocket 服務(wù)器端實(shí)現(xiàn),,比如:

  • Kaazing WebSocket Gateway — 一個(gè) Java 實(shí)現(xiàn)的 WebSocket Server
  • mod_pywebsocket — 一個(gè) Python 實(shí)現(xiàn)的 WebSocket Server
  • Netty —一個(gè) Java 實(shí)現(xiàn)的網(wǎng)絡(luò)框架其中包括了對(duì) WebSocket 的支持
  • node.js —一個(gè) Server 端的 JavaScript 框架提供了對(duì) WebSocket 的支持

如果以上的 WebSocket 服務(wù)端實(shí)現(xiàn)還不能滿(mǎn)足您的業(yè)務(wù)需求的話(huà),開(kāi)發(fā)人員完全可以根據(jù) WebSocket 規(guī)范自己實(shí)現(xiàn)一個(gè)服務(wù)器,。在“WebSocket 實(shí)戰(zhàn)”這一節(jié),,我們將使用 Microsoft .NET 平臺(tái)上的 C# 語(yǔ)言來(lái)打造一個(gè)簡(jiǎn)單的 WebSocket 服務(wù)器,繼而構(gòu)建一個(gè)簡(jiǎn)單的實(shí)時(shí)聊天系統(tǒng),。

回頁(yè)首

WebSocket JavaScript 接口

上一節(jié)介紹了 WebSocket 規(guī)范,,其中主要介紹了 WebSocket 的握手協(xié)議。握手協(xié)議通常是我們?cè)跇?gòu)建 WebSocket 服務(wù)器端的實(shí)現(xiàn)和提供瀏覽器的 WebSocket 支持時(shí)需要考慮的問(wèn)題,,而針對(duì) Web 開(kāi)發(fā)人員的 WebSocket JavaScript 客戶(hù)端接口是非常簡(jiǎn)單的,,以下是 WebSocket JavaScript 接口的定義:

清單 2. WebSocket JavaScript 定義
 [Constructor(in DOMString url, in optional DOMString protocol)] 
 interface WebSocket { 
   readonly attribute DOMString URL; 
        // ready state 
   const unsigned short CONNECTING = 0; 
   const unsigned short OPEN = 1; 
   const unsigned short CLOSED = 2; 
   readonly attribute unsigned short readyState; 
   readonly attribute unsigned long bufferedAmount; 
   //networking 
   attribute Function onopen; 
   attribute Function onmessage; 
   attribute Function onclose; 
   boolean send(in DOMString data); 
   void close(); 
 }; 
 WebSocket implements EventTarget;

其中 URL 屬性代表 WebSocket 服務(wù)器的網(wǎng)絡(luò)地址,協(xié)議通常是”ws”,send 方法就是發(fā)送數(shù)據(jù)到服務(wù)器端,,close 方法就是關(guān)閉連接,。除了這些方法,還有一些很重要的事件:onopen,,onmessage,,onerror 以及 onclose。我們借用 Nettuts 網(wǎng)站上的一張圖來(lái)形象的展示一下 WebSocket 接口:

圖 2. WebSocket JavaScript 接口
圖 2. WebSocket JavaScript 接口

下面是一段簡(jiǎn)單的 JavaScript 代碼展示了怎樣建立 WebSocket 連接和獲取數(shù)據(jù):

清單 3. 建立 WebSocket 連接的實(shí)例 JavaScript 代碼
 var  wsServer = 'ws://localhost:8888/Demo'; 
 var  websocket = new WebSocket(wsServer); 
 websocket.onopen = function (evt) { onOpen(evt) }; 
 websocket.onclose = function (evt) { onClose(evt) }; 
 websocket.onmessage = function (evt) { onMessage(evt) }; 
 websocket.onerror = function (evt) { onError(evt) }; 
 function onOpen(evt) { 
 console.log("Connected to WebSocket server."); 
 } 
 function onClose(evt) { 
 console.log("Disconnected"); 
 } 
 function onMessage(evt) { 
 console.log('Retrieved data from server: ' + evt.data); 
 } 
 function onError(evt) { 
 console.log('Error occured: ' + evt.data); 
 }

回頁(yè)首

瀏覽器支持

下面是主流瀏覽器對(duì) HTML5 WebSocket 的支持情況:

瀏覽器支持情況
ChromeSupported in version 4+
FirefoxSupported in version 4+
Internet ExplorerSupported in version 10+
OperaSupported in version 10+
SafariSupported in version 5+

回頁(yè)首

WebSocket 實(shí)戰(zhàn)

這一節(jié)里我們用一個(gè)案例來(lái)演示怎么使用 WebSocket 構(gòu)建一個(gè)實(shí)時(shí)的 Web 應(yīng)用,。這是一個(gè)簡(jiǎn)單的實(shí)時(shí)多人聊天系統(tǒng),,包括客戶(hù)端和服務(wù)端的實(shí)現(xiàn),。客戶(hù)端通過(guò)瀏覽器向聊天服務(wù)器發(fā)起請(qǐng)求,,服務(wù)器端解析客戶(hù)端發(fā)出的握手請(qǐng)求并產(chǎn)生應(yīng)答信息返回給客戶(hù)端,,從而在客戶(hù)端和服務(wù)器之間建立連接通道。服務(wù)器支持廣播功能,,每個(gè)聊天用戶(hù)發(fā)送的信息會(huì)實(shí)時(shí)的發(fā)送給所有的用戶(hù),,當(dāng)用戶(hù)退出聊天室時(shí),服務(wù)器端需要清理相應(yīng)用戶(hù)的連接信息,,避免資源的泄漏,。以下我們分別從服務(wù)器端和客戶(hù)端來(lái)演示這個(gè) Web 聊天系統(tǒng)的實(shí)現(xiàn),在實(shí)現(xiàn)方式上我們采用了 C# 語(yǔ)言來(lái)實(shí)現(xiàn) WebSocket 服務(wù)器,,而客戶(hù)端是一個(gè)運(yùn)行在瀏覽器里的 HTML 文件,。

WebSocket 服務(wù)器端實(shí)現(xiàn)

這個(gè)聊天服務(wù)器的實(shí)現(xiàn)和基于套接字的網(wǎng)絡(luò)應(yīng)用程序非常類(lèi)似,首先是服務(wù)器端要啟動(dòng)一個(gè)套接字監(jiān)聽(tīng)來(lái)自客戶(hù)端的連接請(qǐng)求,,關(guān)鍵的區(qū)別在于 WebSocket 服務(wù)器需要解析客戶(hù)端的 WebSocket 握手信息,,并根據(jù) WebSocket 規(guī)范的要求產(chǎn)生相應(yīng)的應(yīng)答信息。一旦 WebSocket 連接通道建立以后,,客戶(hù)端和服務(wù)器端的交互就和普通的套接字網(wǎng)絡(luò)應(yīng)用程序是一樣的了,。所以在下面的關(guān)于 WebSocket 服務(wù)器端實(shí)現(xiàn)的描述中,我們主要闡述 WebSocket 服務(wù)器怎樣處理 WebSocket 握手信息,,至于 WebSocket 監(jiān)聽(tīng)端口的建立,,套接字信息流的讀取和寫(xiě)入,都是一些常用的套接字編程的方式,,我們就不多做解釋了,,您可以自行參閱本文的附件源代碼文件。

在描述 WebSocket 規(guī)范時(shí)提到,,一個(gè)典型的 WebSocket Upgrade 信息如下所示:

GET /demo HTTP/1.1 
Host:  
Connection: Upgrade 
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 
Upgrade: WebSocket 
Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5 
Origin: http:// 
[8-byte security key]

其中 Sec-WebSocket-Key1,Sec-WebSocket-Key2 和 [8-byte security key] 這幾個(gè)頭信息是 WebSocket 服務(wù)器用來(lái)生成應(yīng)答信息的來(lái)源,,依據(jù) draft-hixie-thewebsocketprotocol-76 草案的定義,,WebSocket 服務(wù)器基于以下的算法來(lái)產(chǎn)生正確的應(yīng)答信息:

  1. 逐個(gè)字符讀取 Sec-WebSocket-Key1 頭信息中的值,將數(shù)值型字符連接到一起放到一個(gè)臨時(shí)字符串里,,同時(shí)統(tǒng)計(jì)所有空格的數(shù)量,;
  2. 將在第 1 步里生成的數(shù)字字符串轉(zhuǎn)換成一個(gè)整型數(shù)字,然后除以第 1 步里統(tǒng)計(jì)出來(lái)的空格數(shù)量,,將得到的浮點(diǎn)數(shù)轉(zhuǎn)換成整數(shù)型,;
  3. 將第 2 步里生成的整型值轉(zhuǎn)換為符合網(wǎng)絡(luò)傳輸?shù)木W(wǎng)絡(luò)字節(jié)數(shù)組;
  4. 對(duì) Sec-WebSocket-Key2 頭信息同樣進(jìn)行第 1 到第 3 步的操作,,得到另外一個(gè)網(wǎng)絡(luò)字節(jié)數(shù)組,;
  5. 將 [8-byte security key] 和在第 3,,第 4 步里生成的網(wǎng)絡(luò)字節(jié)數(shù)組合并成一個(gè) 16 字節(jié)的數(shù)組;
  6. 對(duì)第 5 步生成的字節(jié)數(shù)組使用 MD5 算法生成一個(gè)哈希值,,這個(gè)哈希值就作為安全密鑰返回給客戶(hù)端,,以表明服務(wù)器端獲取了客戶(hù)端的請(qǐng)求,同意創(chuàng)建 WebSocket 連接

至此,,客戶(hù)端和服務(wù)器的 WebSocket 握手就完成了,,WebSocket 通道也建立起來(lái)了。下面首先介紹一下服務(wù)器端實(shí)現(xiàn)是如何根據(jù)用戶(hù)傳遞的握手信息來(lái)生成網(wǎng)絡(luò)字節(jié)數(shù)組的,。.NET 平臺(tái)提供了很方便的對(duì)字符串,,數(shù)值以及數(shù)組操作的函數(shù),所以生成字節(jié)數(shù)組的方法還是非常簡(jiǎn)單明了的,,代碼如下:

清單 4. 生成網(wǎng)絡(luò)字節(jié)數(shù)組的代碼
    private byte[]   BuildServerPartialKey(string clientKey) 
 { 
      string partialServerKey = ""; 
     byte[] currentKey; 
     int spacesNum = 0; 
     char[] keyChars = clientKey.ToCharArray(); 
     foreach (char currentChar in keyChars) 
     { 
         if (char.IsDigit(currentChar)) partialServerKey += currentChar; 
        if (char.IsWhiteSpace(currentChar)) spacesNum++; 
     } 
     try 
     { 
              currentKey = BitConverter.GetBytes((int)(Int64.Parse(partialServerKey) 
 / spacesNum)); 
        if (BitConverter.IsLittleEndian) Array.Reverse(currentKey); 
     } 
     catch 
     { 
        if (currentKey!= null) Array.Clear(currentKey, 0, currentKey.Length); 
     } 
     return currentKey; 
  }

得到網(wǎng)絡(luò)字節(jié)數(shù)組以后,,服務(wù)器端生成 16 位安全密鑰的方法如下所示:

清單 5. 生成 16 位安全密鑰的代碼
 private byte[] BuildCompleteServerKey(byte[] serverKey1, byte[] serverKey2, 
 byte[] last8Bytes) 
 { 
     byte[] concatenatedKeys = new byte[16]; 
    Array.Copy(serverKey1, 0, concatenatedKeys, 0, 4); 
    Array.Copy(serverKey2, 0, concatenatedKeys, 4, 4); 
    Array.Copy(last8Bytes, 0, concatenatedKeys, 8, 8); 
    System.Security.Cryptography.MD5 MD5Service = 
 System.Security.Cryptography.MD5.Create(); 
   return MD5Service.ComputeHash(concatenatedKeys); 
 }

整個(gè)實(shí)現(xiàn)是非常簡(jiǎn)單明了的,就是將生成的網(wǎng)絡(luò)字節(jié)數(shù)組和客戶(hù)端提交的頭信息里的 [8-byte security key] 合并成一個(gè) 16 位字節(jié)數(shù)組并用 MD5 算法加密,,然后將生成的安全密鑰作為應(yīng)答信息返回給客戶(hù)端,,雙方的 WebSocekt 連接通道就建立起來(lái)了。實(shí)現(xiàn)了 WebSocket 握手信息的處理邏輯,,一個(gè)具有基本功能的 WebSocket 服務(wù)器就完成了,。整個(gè) WebSocket 服務(wù)器由兩個(gè)核心類(lèi)構(gòu)成,一個(gè)是 WebSocketServer,,另外一個(gè)是 SocketConnection,,出于篇幅的考慮,我們不介紹每個(gè)類(lèi)的屬性和方法了,,文章的附件會(huì)給出詳細(xì)的源代碼,,有興趣的讀者可以參考。

服務(wù)器剛啟動(dòng)時(shí)的畫(huà)面如下:

圖 3. WebSocket 服務(wù)器剛啟動(dòng)的畫(huà)面
圖 3. WebSocket 服務(wù)器剛啟動(dòng)的畫(huà)面

客戶(hù)端可以依據(jù)這個(gè)信息填寫(xiě)聊天服務(wù)器的連接地址,,當(dāng)有客戶(hù)端連接到聊天服務(wù)器上時(shí),,服務(wù)器會(huì)打印出客戶(hù)端和服務(wù)器的握手信息,每個(gè)客戶(hù)的聊天信息也會(huì)顯示在服務(wù)器的界面上,,運(yùn)行中的聊天服務(wù)器的界面如下:

圖 4. 有客戶(hù)端連接到 WebSocket 服務(wù)器的
圖 4. 有客戶(hù)端連接到 WebSocket 服務(wù)器的

以上我們簡(jiǎn)單描述了實(shí)現(xiàn)一個(gè) WebSocket 服務(wù)器的最基本的要素,,下一節(jié)我們會(huì)描述客戶(hù)端的實(shí)現(xiàn)。

客戶(hù)端實(shí)現(xiàn)

客戶(hù)端的實(shí)現(xiàn)相對(duì)于服務(wù)器端的實(shí)現(xiàn)來(lái)說(shuō)要簡(jiǎn)單得多了,,我們只需要發(fā)揮想象去設(shè)計(jì) HTML 用戶(hù)界面,,然后呼叫 WebSocket JavaScript 接口來(lái)和 WebSocket 服務(wù)器端來(lái)交互就可以了。當(dāng)然別忘了使用一個(gè)支持 HTML5 和 WebSocket 的瀏覽器,,在筆者寫(xiě)這篇文章的時(shí)候使用的瀏覽器是 Firefox,。客戶(hù)端的頁(yè)面結(jié)構(gòu)是非常簡(jiǎn)潔的,,初始運(yùn)行界面如下:

圖 5. 聊天室客戶(hù)端初始頁(yè)面
圖 5. 聊天室客戶(hù)端初始頁(yè)面

當(dāng)頁(yè)面初次加載的時(shí)候,,首先會(huì)檢測(cè)當(dāng)前的瀏覽器是否支持 WebSocket 并給出相應(yīng)的提示信息,。用戶(hù)按下連接按鈕時(shí),頁(yè)面會(huì)初始化一個(gè)到聊天服務(wù)器的 WebSocekt 連接,,初始化成功以后,,頁(yè)面會(huì)加載對(duì)應(yīng)的 WebSocket 事件處理函數(shù),客戶(hù)端 JavaScript 代碼如下所示:

清單 6. 初始化客戶(hù)端 WebSocket 對(duì)象的代碼
 function ToggleConnectionClicked() {
          if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {  
                ws.close();
            } else {
                Log("準(zhǔn)備連接到聊天服務(wù)器 ...");
                try {
                 ws = 
                 new WebSocket("ws://" + document.getElementById("Connection").value);
                  SocketCreated = true;
                } catch (ex) {
                  Log(ex, "ERROR");
                  return;
                }
                document.getElementById("ToggleConnection").innerHTML = "斷開(kāi)";
                ws.onopen = WSonOpen;
                ws.onmessage = WSonMessage;
                ws.onclose = WSonClose;
                ws.onerror = WSonError;
            }
        };

        function WSonOpen() {
            Log("連接已經(jīng)建立,。", "OK");
            $("#SendDataContainer").show("slow");
        };

        function WSonMessage(event) {
            Log(event.data);            
        };

        function WSonClose() {
            Log("連接關(guān)閉,。", "ERROR");
            document.getElementById("ToggleConnection").innerHTML = "連接";
            $("#SendDataContainer").hide("slow");
        };


        function WSonError() {
            Log("WebSocket錯(cuò)誤。", "ERROR");
        };

當(dāng)用戶(hù)按下發(fā)送按鈕,,客戶(hù)端會(huì)調(diào)用WebSocket對(duì)象向服務(wù)器發(fā)送信息,,并且這個(gè)消息會(huì)廣播給所有的用戶(hù),實(shí)現(xiàn)代碼如下所示:

function SendDataClicked()
 {
            if (document.getElementById("DataToSend").value != "") {
                ws.send(document.getElementById("txtName").value + "說(shuō) :\"" + 
document.getElementById("DataToSend").value + "\"");
                document.getElementById("DataToSend").value = "";
            }
        };

如果有多個(gè)用戶(hù)登錄到聊天服務(wù)器,,客戶(hù)端頁(yè)面的運(yùn)行效果如下所示:

圖 6. 聊天客戶(hù)端運(yùn)行頁(yè)面
圖 6. 聊天客戶(hù)端運(yùn)行頁(yè)面

至此我們已經(jīng)完成了一個(gè)完整的 WebSocket 客戶(hù)端實(shí)現(xiàn),,用戶(hù)可以體驗(yàn)一下這個(gè)聊天室的簡(jiǎn)單和快捷,完全不用考慮頁(yè)面的刷新和繁瑣的 Ajax 調(diào)用,,享受桌面程序的用戶(hù)體驗(yàn),。WebSocket 的強(qiáng)大和易用可見(jiàn)一斑,您完全可以在這個(gè)基礎(chǔ)上加入更多的功能,,設(shè)計(jì)更加漂亮的用戶(hù)界面,,切身體驗(yàn) WebSocket 的震撼力。完整的客戶(hù)端代碼請(qǐng)參閱附件提供的源代碼,。

回頁(yè)首

WebSocket 的局限性

WebSocket 的優(yōu)點(diǎn)已經(jīng)列舉得很多了,,但是作為一個(gè)正在演變中的 Web 規(guī)范,我們也要看到目前用 Websocket 構(gòu)建應(yīng)用程序的一些風(fēng)險(xiǎn),。首先,,WebSocket 規(guī)范目前還處于草案階段,也就是它的規(guī)范和 API 還是有變動(dòng)的可能,,另外的一個(gè)風(fēng)險(xiǎn)就是微軟的 IE 作為占市場(chǎng)份額最大的瀏覽器,,和其他的主流瀏覽器相比,對(duì) HTML5 的支持是比較差的,,這是我們?cè)跇?gòu)建企業(yè)級(jí)的 Web 應(yīng)用的時(shí)候必須要考慮的一個(gè)問(wèn)題,。

回頁(yè)首

總結(jié)

本文介紹了 HTML5 WebSocket 的橫空出世以及它嘗試解決的的問(wèn)題,然后介紹了 WebSocket 規(guī)范和 WebSocket 接口,,以及和傳統(tǒng)的實(shí)時(shí)技術(shù)相比在性能上的優(yōu)勢(shì),并且演示了怎樣使用 WebSocket 構(gòu)建一個(gè)實(shí)時(shí)的 Web 應(yīng)用,,最后我們介紹了當(dāng)前的主流瀏覽器對(duì) HTML5 的支持情況和 WebSocket 的局限性,。不過(guò),我們應(yīng)該看到,,盡管 HTML5 WebSocket 目前還有一些局限性,,但是已經(jīng)是大勢(shì)所趨,,微軟也明確表達(dá)了未來(lái)對(duì) HTML5 的支持,而且這些支持我們可以在 Windows 8 和 IE10 里看到,,我們也在各種移動(dòng)設(shè)備,,平板電腦上看到了 HTML5 和 WebSocket 的身影。WebSocket 將會(huì)成為未來(lái)開(kāi)發(fā)實(shí)時(shí) Web 應(yīng)用的生力軍應(yīng)該是毫無(wú)懸念的了,,作為 Web 開(kāi)發(fā)人員,,關(guān)注 HTML5,關(guān)注 WebSocket 也應(yīng)該提上日程了,,否則我們?cè)谛乱惠喌能浖镄碌睦顺敝兄荒茏霰谏嫌^(guān)了,。

回頁(yè)首

下載

描述名字大小
示例代碼new-source.zip94KB

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀(guān)點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多