及時(shí)通信技術(shù)

Ajax短輪詢:腳本發(fā)送的http請求

在第一種方式中,瀏覽器在收到數(shù)據(jù)后會直接調(diào)用JS回調(diào)函數(shù),但是這種方式該如何響應(yīng)數(shù)據(jù)呢?可以通過在返回?cái)?shù)據(jù)中嵌入JS腳本的方式,如“js_func(“data from server ”)”,服務(wù)器端將返回的數(shù)據(jù)作為回調(diào)函數(shù)的參數(shù),瀏覽器在收到數(shù)據(jù)后就會執(zhí)行這段JS腳本。

但是這種方式有一個(gè)明顯的不足之處:IE、Morzilla Firefox 下端的進(jìn)度欄都會顯示加載沒有完成,而且 IE 上方的圖標(biāo)會不停的轉(zhuǎn)動(dòng),表示加載正在進(jìn)行。Google 的天才們使用一個(gè)稱為“htmlfile”的 ActiveX 解決了在 IE 中的加載顯示問題,并將這種方法應(yīng)用到了 gmail+gtalk 產(chǎn)品中。

Websocket:未來的解決方案1

如果說Ajax的出現(xiàn)是互聯(lián)網(wǎng)發(fā)展的必然,那么Comet技術(shù)的出現(xiàn)則更多透露出一種無奈,僅僅作為一種hack技術(shù),因?yàn)闆]有更好的解決方案。Comet解決的問題應(yīng)該由誰來解決才是合理的呢?瀏覽器,html標(biāo)準(zhǔn),還是http標(biāo)準(zhǔn)?主角應(yīng)該是誰呢?本質(zhì)上講,這涉及到數(shù)據(jù)傳輸方式,http協(xié)議應(yīng)首當(dāng)其沖,是時(shí)候改變一下這個(gè)懶惰的協(xié)議的請求/響應(yīng)模式了。

W3C給出了答案,在新一代html標(biāo)準(zhǔn)html5中提供了一種瀏覽器和服務(wù)器間進(jìn)行全雙工通訊的網(wǎng)絡(luò)技術(shù)Websocket。從Websocket草案得知,Websocket是一個(gè)全新的、獨(dú)立的協(xié)議,基于TCP協(xié)議,與http協(xié)議兼容、卻不會融入http協(xié)議,僅僅作為html5的一部分。于是乎腳本又被賦予了另一種能力:發(fā)起websocket請求。這種方式我們應(yīng)該很熟悉,因?yàn)锳jax就是這么做的,所不同的是,Ajax發(fā)起的是http請求而已。

與http協(xié)議不同的請求/響應(yīng)模式不同,Websocket在建立連接之前有一個(gè)Handshake(Opening Handshake)過程,在關(guān)閉連接前也有一個(gè)Handshake(Closing Handshake)過程,建立連接之后,雙方即可雙向通信。

有關(guān)WebSocket的詳細(xì)介,請參見即時(shí)通訊網(wǎng)有關(guān)WebSocket的系列文章:《WebSocket詳解(一):初步認(rèn)識WebSocket技術(shù)》、《WebSocket詳解(二):技術(shù)原理、代碼演示和應(yīng)用案例》、《WebSocket詳解(三):深入WebSocket通信協(xié)議細(xì)節(jié)》。

從瀏覽器支持角度來看,WebSocket已經(jīng)近在眼前,但?仍有一段較長的路要走,特別是在中國這個(gè)IE6、7、8依然盛行的國家,舊版本瀏覽器的消亡需要很長一段時(shí)間,在完全實(shí)現(xiàn)瀏覽器全兼容前,Comet技術(shù)可能仍然是最好的解決方案。不過,當(dāng)前也已存在一些比較成熟的封裝方案來解決這種兼容性限制,比如:開源的Socket.io,詳見《Socket.IO介紹:支持WebSocket、用于WEB端的即時(shí)通訊的框架》。

SSE:未來的解決方案2

SSE(Server-Sent Event,服務(wù)端推送事件)是一種允許服務(wù)端向客戶端推送新數(shù)據(jù)的HTML5技術(shù)。與由客戶端每隔幾秒從服務(wù)端輪詢拉取新數(shù)據(jù)相比,這是一種更優(yōu)的解決方案。

與WebSocket?相比,它也能從服務(wù)端向客戶端推送數(shù)據(jù)。那如何決定你是用SSE還是WebSocket呢?概括來說,WebSocket能做的,SSE也能做,反之亦然,但在完成某些任務(wù)方面,它們各有千秋。

WebSocket是一種更為復(fù)雜的服務(wù)端實(shí)現(xiàn)技術(shù),但它是真正的雙向傳輸技術(shù),既能從服務(wù)端向客戶端推送數(shù)據(jù),也能從客戶端向服務(wù)端推送數(shù)據(jù)。

WebSocket和SSE的瀏覽器支持率差不多,大多數(shù)主流桌面瀏覽器兩者都支持。在Android 4.3以及更早的版本中,系統(tǒng)默認(rèn)瀏覽器兩者都不支持,F(xiàn)irefox和Chrome則完全支持;Android 4.4中,系統(tǒng)默認(rèn)瀏覽器兩者都支持;Safari從5.0開始支持SSE(iOS系統(tǒng)從4.0開始),但直到6.0才正確地支持WebSocket(6.0之前的Safari所實(shí)現(xiàn)的WebSocket協(xié)議存在安全問題,所以一些主流瀏覽器已經(jīng)禁用了基于這個(gè)協(xié)議的實(shí)現(xiàn))。

與WebSocket相比,SSE有一些顯著的優(yōu)勢。個(gè)人認(rèn)為它最大的優(yōu)勢就是便利:不需要添加任何新組件,用任何你習(xí)慣的后端語言和框架就能繼續(xù)使用。你不用為新建虛擬機(jī)、弄一個(gè)新的IP或新的端口號而勞神,就像在現(xiàn)有網(wǎng)站中新增一個(gè)頁面那樣簡單。我喜歡把這稱為既存基礎(chǔ)設(shè)施優(yōu)勢。

SSE的第二個(gè)優(yōu)勢是服務(wù)端的簡潔。相對而言,WebSocket則很復(fù)雜,不借助輔助類庫基本搞不定(我試過,令人痛苦)。

因?yàn)镾SE能在現(xiàn)有的HTTP/HTTPS協(xié)議上運(yùn)作,所以它能直接運(yùn)行于現(xiàn)有的代理服務(wù)器和認(rèn)證技術(shù)。而對WebSocket而言,代理服務(wù)器需要做一些開發(fā)(或其他工作)才能支持,在寫這本書時(shí),很多服務(wù)器還沒有(雖然這種狀況會改善)。SSE還有一個(gè)優(yōu)勢:它是一種文本協(xié)議,腳本調(diào)試非常容易。事實(shí)上,在本書中,我們會在開發(fā)和測試時(shí)用curl,甚至直接在命令行中運(yùn)行后端腳本。

不過,這就引出了WebSocket相較SSE的一個(gè)潛在優(yōu)勢:WebSocket是二進(jìn)制協(xié)議,而SSE是文本協(xié)議(通常使用UTF-8編碼)。當(dāng)然,我們可以通過SSE連接傳輸二進(jìn)制數(shù)據(jù):在SSE中,只有兩個(gè)具有特殊意義的字符,它們是CR和LF,而對它們進(jìn)行轉(zhuǎn)碼并不難。但用SSE傳輸二進(jìn)制數(shù)據(jù)時(shí)數(shù)據(jù)會變大,如果需要從服務(wù)端到客戶端傳輸大量的二進(jìn)制數(shù)據(jù),最好還是用WebSocket。

WebSocket相較SSE最大的優(yōu)勢在于它是雙向交流的,這意味向服務(wù)端發(fā)送數(shù)據(jù)就像從服務(wù)端接收數(shù)據(jù)一樣簡單。用SSE時(shí),一般通過一個(gè)獨(dú)立的Ajax請求從客戶端向服務(wù)端傳送數(shù)據(jù)。相對于WebSocket,這樣使用Ajax會增加開銷,但也就多一點(diǎn)點(diǎn)而已。如此一來,問題就變成了“什么時(shí)候需要關(guān)心這個(gè)差異?”如果需要以1次/秒或者更快的頻率向服務(wù)端傳輸數(shù)據(jù),那應(yīng)該用WebSocket。0.2次/秒到1次/秒的頻率是一個(gè)灰色地帶,用WebSocket和用SSE差別不大;但如果你期望重負(fù)載,那就有必要確定基準(zhǔn)點(diǎn)。頻率低于0.2次/秒左右時(shí),兩者差別不大。

從服務(wù)端向客戶端傳輸數(shù)據(jù)的性能如何?如果是文本數(shù)據(jù)而非二進(jìn)制數(shù)據(jù)(如前文所提到的),SSE和WebSocket沒什么區(qū)別。它們都用TCP/IP套接字,都是輕量級協(xié)議。延遲、帶寬、服務(wù)器負(fù)載等都沒有區(qū)別,除非……呃?除非什么?

當(dāng)你在享用SSE的既存基礎(chǔ)設(shè)施優(yōu)勢,并在客戶端和服務(wù)端腳本之間設(shè)了一個(gè)網(wǎng)絡(luò)服務(wù)器,區(qū)別就顯現(xiàn)出來了。一個(gè)SSE連接不僅使用一個(gè)套接字,還會占用一個(gè)Apache線程或進(jìn)程,如果用PHP,它會為這個(gè)連接專門創(chuàng)建一個(gè)PHP新實(shí)例。Apache和PHP會使用大量的內(nèi)存,這會限制服務(wù)器所能支持的并行連接數(shù)。所以,要做到用SSE在數(shù)據(jù)傳輸性能上和WebSocket完全一樣,需要寫一個(gè)自己的后端服務(wù)器,當(dāng)然,那些在任何情況下都會用自己的服務(wù)器并使用Node.js的人,會覺得這有什么稀奇的。

說一下WebSocket在舊版本瀏覽器上的兼容。?當(dāng)前,大約超過2/3的瀏覽器支持這些新技術(shù),移動(dòng)端瀏覽器的支持率會低一些。依慣例,每當(dāng)需要雙向套接字時(shí),就會用到Flash,并且WebSocket的向后兼容通常是用Flash來做,這已經(jīng)相當(dāng)復(fù)雜了,如果瀏覽器上沒有Flash,情況更糟。概括來說,WebSocket難兼容,SSE易兼容。

有關(guān)SSE的詳細(xì)介紹文章請參見:《SSE技術(shù)詳解:一種全新的HTML5服務(wù)器推送事件技術(shù)》。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容