WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。它實現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信——允許服務(wù)器主動發(fā)送信息給客戶端。
WebSocket通信協(xié)議于2011年被IETF定為標準RFC 6455,并被RFC7936所補充規(guī)范。
一、WebSocket簡介
webSocket是什么:
1、WebSocket是一種在單個TCP連接上進行全雙工通信的協(xié)議
2、WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù)
3、在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進行雙向數(shù)據(jù)傳輸
4、需要安裝第三方包:cmd中:go get -u -v github.com/gorilla/websocket
WebSocket 是一種標準協(xié)議,用于在客戶端和服務(wù)端之間進行雙向數(shù)據(jù)傳輸。但它跟 HTTP 沒什么關(guān)系,它是一種基于 TCP 的一種獨立實現(xiàn)。
以前客戶端想知道服務(wù)端的處理進度,要不停地使用 Ajax 進行輪詢,讓瀏覽器隔個幾秒就向服務(wù)器發(fā)一次請求,這對服務(wù)器壓力較高。另外一種輪詢就是采用 long poll 的方式,這就跟打電話差不多,沒收到消息就一直不掛電話,也就是說,客戶端發(fā)起連接后,如果沒消息,就一直不返回 Response 給客戶端,連接階段一直是阻塞的。
而 WebSocket 解決了 HTTP 的這幾個難題。首先,當服務(wù)器完成協(xié)議升級后( HTTP -> WebSocket ),服務(wù)端可以主動推送信息給客戶端,解決了輪詢造成的同步延遲問題。由于 WebSocket 只需要一次 HTTP 握手,服務(wù)端就能一直與客戶端保持通訊,直到關(guān)閉連接,這樣就解決了服務(wù)器需要反復解析 HTTP 協(xié)議,減少了資源的開銷。
WebSocket協(xié)議支持(在受控環(huán)境中運行不受信任的代碼的)客戶端與(選擇加入該代碼的通信的)遠程主機之間進行全雙工通信。用于此的安全模型是Web瀏覽器常用的基于原始的安全模式。 協(xié)議包括一個開放的握手以及隨后的TCP層上的消息幀。 該技術(shù)的目標是為基于瀏覽器的、需要和服務(wù)器進行雙向通信的(服務(wù)器不能依賴于打開多個HTTP連接(例如,使用XMLHttpRequest或和長輪詢))應(yīng)用程序提供一種通信機制。
websocket 是一個基于應(yīng)用層的網(wǎng)絡(luò)協(xié)議,建立在tcp 協(xié)議之上,和 http 協(xié)議可以說是兄弟的關(guān)系,但是這個兄弟有點依賴 http ,為什么這么說呢?我們都知道 HTTP 實現(xiàn)了三次握手來建立通信連接,實際上 websocket 的創(chuàng)始人很聰明,他不想重復的去造輪子,反正我兄弟已經(jīng)實現(xiàn)了握手了,我干嘛還要重寫一套呢?先讓它去沖鋒陷陣呢,我坐收漁翁之利不是更香 嗎,所以一般來說,我們會先用 HTTP 先進行三次握手,再向服務(wù)器請求升級為websocket 協(xié)議,這就好比說,嘿兄弟你先去給我排個隊占個坑位建個小房子,到時候我在把這房子改造成摩天大樓。而且一般來說 80 和 443 端口一般 web 服務(wù)端都會外放出去,這樣可以有效的避免防火墻的限制。當然,你創(chuàng)建的 websocket 服務(wù)端進程的端口也需要外放出去。
很多人會想問,web開發(fā) 使用 HTTP 協(xié)議不是已經(jīng)差不多夠用了嗎?為什么還要我再多學一種呢?這不是搞事情嘛,仔細想想,一門新技術(shù)的產(chǎn)生必然有原因的,如果沒有需求,我們干嘛那么蛋疼去寫那么多東西,就是因為 HTTP 這個協(xié)議有些業(yè)務(wù)需求支持太過于雞肋了,從 HTTP 0.9 到現(xiàn)在的 HTTP3.0 ,HTTP協(xié)議可以說說是在普通的web開發(fā)領(lǐng)域已經(jīng)是十分完善且高效的了,說這個協(xié)議養(yǎng)活了全球半數(shù)的公司也不為過吧,像 2.0 服務(wù)器推送技術(shù),3.0 采用了 UDP 而放棄了原來的 TCP ,這些改動都是為了進一步提升協(xié)議的性能,然而大家現(xiàn)在還是基本使用的 HTTP 1.1 這個最為經(jīng)典的協(xié)議, 也是讓開發(fā)者挺尷尬的。
絕大多數(shù)的web開發(fā)都是應(yīng)用層開發(fā)者,大多數(shù)都是基于已有的應(yīng)用層去開發(fā)應(yīng)用,可以說我們最熟悉、日常打交道最多的就是應(yīng)用層協(xié)議了,底下 TCP/IP 協(xié)議我們基本很少會去處理,當然大廠可能就不一樣了,自己弄一套協(xié)議也是正常的,這大概也是程序員和碼農(nóng)的區(qū)別吧,搬磚還是創(chuàng)新,差別還是很大的。網(wǎng)絡(luò)這種分層協(xié)議的好處我在之前的文章也說過了,這種隔離性很方便就可以讓我們基于原來的基礎(chǔ)去拓展,具有較好的兼容性。
總的來說,它就是一種依賴HTTP協(xié)議的,支持全雙工通信的一種應(yīng)用層網(wǎng)絡(luò)協(xié)議。
二、WebSocket產(chǎn)生背景
簡單的說,WebSocket協(xié)議之前,雙工通信是通過多個http鏈接來實現(xiàn),這導致了效率低下。WebSocket解決了這個問題。下面是標準RFC6455中的產(chǎn)生背景概述。
長久以來, 創(chuàng)建實現(xiàn)客戶端和用戶端之間雙工通訊的web app都會造成HTTP輪詢的濫用: 客戶端向主機不斷發(fā)送不同的HTTP呼叫來進行詢問。
這會導致一系列的問題:
- 1.服務(wù)器被迫為每個客戶端使用許多不同的底層TCP連接:一個用于向客戶端發(fā)送信息,其它用于接收每個傳入消息。
- 2.有些協(xié)議有很高的開銷,每一個客戶端和服務(wù)器之間都有HTTP頭。
- 3.客戶端腳本被迫維護從傳出連接到傳入連接的映射來追蹤回復。
一個更簡單的解決方案是使用單個TCP連接雙向通信。 這就是WebSocket協(xié)議所提供的功能。 結(jié)合WebSocket API ,WebSocket協(xié)議提供了一個用來替代HTTP輪詢實現(xiàn)網(wǎng)頁到遠程主機的雙向通信的方法。
WebSocket協(xié)議被設(shè)計來取代用HTTP作為傳輸層的雙向通訊技術(shù),這些技術(shù)只能犧牲效率和可依賴性其中一方來提高另一方,因為HTTP最初的目的不是為了雙向通訊。
三、WebSocket實現(xiàn)原理
在實現(xiàn)websocket連線過程中,需要通過瀏覽器發(fā)出websocket連線請求,然后服務(wù)器發(fā)出回應(yīng),這個過程通常稱為“握手” 。**在 WebSocket API,瀏覽器和服務(wù)器只需要做一個握手的動作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。**在此WebSocket 協(xié)議中,為我們實現(xiàn)即時服務(wù)帶來了兩大好處:
- Header:互相溝通的Header是很小的-大概只有 2 Bytes。
- Server Push:服務(wù)器的推送,服務(wù)器不再被動的接收到瀏覽器的請求之后才返回數(shù)據(jù),而是在有新數(shù)據(jù)時就主動推送給瀏覽器。
四、WebSocket協(xié)議舉例
瀏覽器請求:
- GET /webfin/websocket/ HTTP/1.1。
- Host: localhost。
- Upgrade: websocket。
- Connection: Upgrade。
- Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==。
- Origin: http://服務(wù)器地址。
- Sec-WebSocket-Version: 13。
服務(wù)器回應(yīng):
- HTTP/1.1 101 Switching Protocols。
- Upgrade: websocket。
- Connection: Upgrade。
- Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=。
- WebSocket借用http請求進行握手,相比正常的http請求,多了一些內(nèi)容。其中:
- Upgrade: websocket。
- Connection: Upgrade。
- 表示希望將http協(xié)議升級到Websocket協(xié)議。Sec-WebSocket-Key是瀏覽器隨機生成的base64 encode的值,用來詢問服務(wù)器是否是支持WebSocket。
服務(wù)器返回:
- Upgrade: websocket。
- Connection: Upgrade。
- 告訴瀏覽器即將升級的是Websocket協(xié)議
Sec-WebSocket-Accept是將請求包“Sec-WebSocket-Key”的值,與”258EAFA5-E914-47DA-95CA-C5AB0DC85B11″這個字符串進行拼接,然后對拼接后的字符串進行sha-1運算,再進行base64編碼得到的。用來說明自己是WebSocket助理服務(wù)器。
Sec-WebSocket-Version是WebSocket協(xié)議版本號。RFC6455要求使用的版本是13,之前草案的版本均應(yīng)當被棄用。
五、WebSocket使用
1.WebSocket 介紹
WebSocket 發(fā)起單個請求,服務(wù)端不需要等待客服端,客戶端在任何時候也能發(fā)消息到服務(wù)端,減少了輪詢時候的延遲.經(jīng)歷一次連接后,服務(wù)器能給客戶端發(fā)多次。下圖是輪詢與WebSocket的區(qū)別。
基于http的實時消息是相當?shù)膹碗s,在無狀態(tài)的請求中維持回話的狀態(tài)增加了復雜度,跨域也很麻煩,使用ajax處理請求有序請求需要考慮更多。通過ajax進行交流也不簡單。每一個延伸http功能的目的不是增加他的復雜度。websocket 可以大大簡化實時通信應(yīng)用中的鏈接。
Websocket是一種底層網(wǎng)絡(luò)協(xié)議,可以讓你在這個基礎(chǔ)上建立別的標準協(xié)議。比如在WebSocket的客戶端的基礎(chǔ)上使用XMPP登錄不同的聊天服務(wù)器,因為所有的XMPP服務(wù)理解相同的標準協(xié)議。WebSocket是web應(yīng)用的一種創(chuàng)新。
為了與其他平臺競爭,WebSocket是H5應(yīng)用提供的一部分先進功能。每個操作系統(tǒng)都需要網(wǎng)絡(luò)功能,能夠讓應(yīng)用使用Sockets與別的主機進行通信,是每個大平臺的核心功能。在很多方面,讓Web應(yīng)用表現(xiàn)的像操作系統(tǒng)平臺是html5的趨勢。像socket這樣底層的網(wǎng)絡(luò)協(xié)議APIs不會符合原始的安全模型,也不會有web api那樣的設(shè)計風格。WebSocket給H5應(yīng)用提供TCP的方式不會消弱網(wǎng)絡(luò)安全且有現(xiàn)代的Api。
WebSocket是Html5平臺的一個重要組件也是開發(fā)者強有力的工具。簡單的說,你需要WebSocket創(chuàng)建世界級的web應(yīng)用。它彌補了http不適合實時通信的重大缺陷。異步、雙向通信模式,通過傳輸層協(xié)議使WebSocket具有普遍靈活性。想象一下你能用WebSocket創(chuàng)建正真實實時應(yīng)用的所有方式。比如聊天、協(xié)作文檔編輯、大規(guī)模多人在線游戲(MMO),股票交易應(yīng)用等等。
WebSocket是一個協(xié)議,但也有一個WebSocket API,這讓你的應(yīng)用去控制WebSocket的協(xié)議去響應(yīng)被服務(wù)端觸發(fā)的事件。API是W3C開發(fā),協(xié)議是IETE制定。現(xiàn)代瀏覽器支持WebSocket API,這包括使用全雙工和雙向鏈接的方法和特性。讓你執(zhí)行像打開關(guān)閉鏈接、發(fā)送接收消息、監(jiān)聽服務(wù)端事件等必要操作。
2.WebSocket API
WebSocket API其實就是一個使用WebSocket協(xié)議的接口,通過它來建立全雙工通道來收發(fā)消息,簡單易學,要連接遠程服務(wù)器,只需要創(chuàng)建一個WebSocket對象實體,并傳入一個服務(wù)端的URL。在客戶端和服務(wù)端一開始握手的期間,http協(xié)議升級到WebSocket協(xié)議就建立了連接,底層都是TCP協(xié)議。一旦建立連接,通過WebSocket接口可以反復的發(fā)送消息。在你的代碼里面,你可以使用異步事件監(jiān)聽連接生命周期的每個階段。
WebSocket API是純事件驅(qū)動,一旦建立全雙工連接,當服務(wù)端給客戶端發(fā)送數(shù)據(jù)或者資源,它能自動發(fā)送狀態(tài)改變的數(shù)據(jù)和通知。所以你不需要為了狀態(tài)的更新而去輪訓Server,在客戶端監(jiān)聽即可。
首先,我們需要通過調(diào)用WebSocket構(gòu)造函數(shù)來創(chuàng)建一個WebSocket連接,構(gòu)造函數(shù)會返回一個WebSocket實例,可以用來監(jiān)聽事件。這些事件會告訴你什么時候連接建立,什么時候消息到達,什么時候連接關(guān)閉了,以及什么時候發(fā)生了錯誤。WebSocket協(xié)議定義了兩種URL方案,WS和WSS分別代表了客戶端和服務(wù)端之間未加密和加密的通信。WS(WebSocket)類似于Http URL,而WSS(WebSocket Security)URL 表示連接是基于安全傳輸層(TLS/SSL)和https的連接是同樣的安全機制。
WebSocket的構(gòu)造函數(shù)需要一個URL參數(shù)和一個可選的協(xié)議參數(shù)(一個或者多個協(xié)議的名字),協(xié)議的參數(shù)例如XMPP(Extensible Messaging and Presence Protocol)、SOAP(Simple Object Access Protocol)或者自定義協(xié)議。而URL參數(shù)需要以WS://或者WSS://開頭,例如:ws://www.websocket.org,如果URL有語法錯誤,構(gòu)造函數(shù)會拋出異常。
var ws = new WebSocket("ws://www.websocket.org");
//測試了下鏈接不上。
第二個參數(shù)是協(xié)議名稱,是可選的,服務(wù)端和客服端使用的協(xié)議必須一致,這樣收發(fā)消息彼此才能理解,你可以定義一個或多個客戶端使用的協(xié)議,服務(wù)端會選擇一個來使用,一個客服端和一個服務(wù)端之間只能有一個協(xié)議。當然都得基于WebSocket,WebSocket的重大好處之一就是基于WebSocket協(xié)議的廣泛使用,讓你的Web能夠擁有傳統(tǒng)桌面程序那樣的能力。
言歸正傳,我們回到構(gòu)造函數(shù),在第一次握手之后,和協(xié)議的名稱一起,客戶端會發(fā)送一個Sec-WebSocket-Protocol 頭,服務(wù)端會選擇0個或一個協(xié)議,響應(yīng)會帶上同樣的Sec-WebSocket-Protocol 頭,否則會關(guān)閉連接。通過協(xié)議協(xié)商(Protocol negotiation ),我們可以知道給定的WebSocket服務(wù)器所支持的協(xié)議和版本,然后應(yīng)用選擇協(xié)議使用。
var ws = new WebSocket("ws://echo.websocket.org", "myProtocol");
//myProtocol 是假設(shè)的一個定義好的且符合標準的協(xié)議。
你可以傳遞一個協(xié)議的數(shù)組。
//服務(wù)端會選擇其中一個使用
echoSocket.onopen = function(e) {
// Check the protocol chosen by the server
console.log(echoSocket.protocol);
}
輸出:com.kaazing.ech
協(xié)議這個參數(shù)有三種。
1.注冊協(xié)議:根據(jù)RFC6455(WebSocket 協(xié)議)和IANA被官方注冊的標準協(xié)議。例如 微軟的SOAP。
看到兩個華為的:
2.開放協(xié)議:被廣泛使用的標注協(xié)議,例如XMPP和STOMP。但沒有被正式注冊。
3.自定義協(xié)議:自己編寫和使用的WebSocket的協(xié)議。 協(xié)議會再后續(xù)章節(jié)給出詳細介紹,下面先看事件、對象和方法以及實例。
3.WebSocket事件
WebSocket API是純事件驅(qū)動,通過監(jiān)聽事件可以處理到來的數(shù)據(jù)和改變的鏈接狀態(tài)??蛻舳瞬恍枰獮榱烁聰?shù)據(jù)而輪訓服務(wù)器。服務(wù)端發(fā)送數(shù)據(jù)后,消息和事件會異步到達。WebSocket編程遵循一個異步編程模型,只需要對WebSocket對象增加回調(diào)函數(shù)就可以監(jiān)聽事件。你也可以使用addEventListener()方法來監(jiān)聽。而一個WebSocket對象分四類不同事件。
1.open
一旦服務(wù)端響應(yīng)WebSocket連接請求,就會觸發(fā)open事件。響應(yīng)的回調(diào)函數(shù)稱為onopen。
ws.onopen = function(e) {
console.log("Connection open...");
};
open事件觸發(fā)的時候,意味著協(xié)議握手結(jié)束,WebSocket已經(jīng)準備好收發(fā)數(shù)據(jù)。如果你的應(yīng)用收到open事件,就可以確定服務(wù)端已經(jīng)處理了建立連接的請求,且同意和你的應(yīng)用通信。
2.Message
當消息被接受會觸發(fā)消息事件,響應(yīng)的回調(diào)函數(shù)叫做onmessage。如下:
ws.onmessage = function(e) {
if(typeof e.data === "string"){
console.log("String message received", e, e.data);
} else {
console.log("Other message received", e, e.data);
}
};
除了文本消息,WebSocket消息機制還能處理二進制數(shù)據(jù),有Blob和ArrayBuffer兩種類型,在讀取到數(shù)據(jù)之前需要決定好數(shù)據(jù)的類型。
ws.binaryType = "blob";
// Event handler for receiving Blob messages
ws.onmessage = function(e) {
if(e.data instanceof Blob){
console.log("Blob message received", e.data);
var blob = new Blob(e.data);
}
};
ws.binaryType = "arraybuffer";
ws.onmessage = function(e) {
if(e.data instanceof ArrayBuffer){
console.log("ArrayBuffer Message Received", + e.data);
// e.data即ArrayBuffer類型
var a = new Uint8Array(e.data);
}
};
3.Error
如果發(fā)生意外的失敗會觸發(fā)error事件,相應(yīng)的函數(shù)稱為onerror,錯誤會導致連接關(guān)閉。如果你收到一個錯誤事件,那么你很快會收到一個關(guān)閉事件,在關(guān)閉事件中也許會告訴你錯誤的原因。而對錯誤事件的處理比較適合做重連的邏輯。
ws.onerror = function(e) {
console.log("WebSocket Error: " , e);
//Custom function for handling errors
handleErrors(e);
};
4.Close
不言而喻,當連接關(guān)閉的時候回觸發(fā)這個事件,對應(yīng)onclose方法,連接關(guān)閉之后,服務(wù)端和客戶端就不能再收發(fā)消息。
WebSocket的規(guī)范其實還定義了ping和pong 架構(gòu)(frames),可以用來做keep-alive,心跳,網(wǎng)絡(luò)狀態(tài)查詢,latency instrumentation(延遲儀表?),但是目前 WebSocket API還沒有公布這些特性,盡管瀏覽器支持了ping,但不會觸發(fā)ping事件,相反,瀏覽器會自動響應(yīng)pong,第八章會將更多關(guān)于ping和pong的細節(jié)。
當然你可以調(diào)用close方法斷開與服務(wù)端的鏈接來觸發(fā)onclose事件:
console.log("Connection closed", e);
};
連接失敗和成功的關(guān)閉握手都會觸發(fā)關(guān)閉事件,WebSocket的對象的readyState屬性就代表連接的狀態(tài)(2代表正在關(guān)閉,3代表已經(jīng)關(guān)閉)。關(guān)閉事件有三個屬性可以用來做異常處理和重獲: wasClean,code和reason。wasClean是一個bool值,代表連接是否干凈的關(guān)閉。 如果是響應(yīng)服務(wù)端的close事件,這個值為true,如果是別的原因,比如因為是底層TCP連接關(guān)閉,wasClean為false。code和reason代表關(guān)閉連接時服務(wù)端發(fā)送的狀態(tài),這兩個屬性和給入close方法的code和reason參數(shù)是對應(yīng)的,稍后會描述細節(jié)。
4.WebSocket 方法
WebSocket 對象有兩個方法:send()和close()。
1.send()
一旦在服務(wù)端和客戶端建立了全雙工的雙向連接,可以使用send方法去發(fā)送消息。
ws.send("Hello WebSocket!");
當連接是open的時候send()方法傳送數(shù)據(jù),當連接關(guān)閉或獲取不到的時候回拋出異常。一個通常的錯誤是人們喜歡在連接open之前發(fā)送消息。如下所示:
var ws = new WebSocket("ws://echo.websocket.org")
ws.send("Initial data");
正確的姿勢如下,應(yīng)該等待open事件觸發(fā)后再發(fā)送消息。
ws.onopen = function(e) {
ws.s
如果想通過響應(yīng)別的事件去發(fā)送消息,可以檢查readyState屬性的值為open的時候來實現(xiàn)。
if (ws.readyState === WebSocket.OPEN) {
//open的時候即可發(fā)送
ws.send(data);
} else {
// Do something else in this case.
//Possibly ignore the data or enqueue it.
}
}
發(fā)送二進制數(shù)據(jù):
var blob = new Blob("blob contents");
ws.send(blob);
// Send an ArrayBuffer
var a = new Uint8Array([8,6,7,5,3,0,9]);
ws.send(a.buffer);
Blob對象和JavaScript File API一起使用的時候相當有用,可以發(fā)送或接受文件,大部分的多媒體文件,圖像,視頻和音頻文件。這一章末尾會結(jié)合File API提供讀取文件內(nèi)容來發(fā)送WebSocket消息的實例代碼。
2.close()
使用close方法來關(guān)閉連接,如果連接以及關(guān)閉,這方法將什么也不做。調(diào)用close方法只后,將不能發(fā)送數(shù)據(jù)。
close方法可以傳入兩個可選的參數(shù),code(numerical)和reason(string),以告訴服務(wù)端為什么終止連接。第三章講到關(guān)閉握手的時候再詳細討論這兩個參數(shù)。
ws.close(1000, "Closing normally");
//1000是狀態(tài)碼,代表正常結(jié)束。
5.WebSocket 屬性
WebSocket對象有三個屬性,readyState,bufferedAmount和Protocol。
1.readyState
WebSocket對象通過只讀屬性readyState來傳達連接狀態(tài),它會更加連接狀態(tài)自動改變。下表展示了readyState屬性的四個不同的值。
了解當前連接的狀態(tài)有助于我們調(diào)試。
2.bufferedAmount
有時候需要檢查傳輸數(shù)據(jù)的大小,尤其是客戶端傳輸大量數(shù)據(jù)的時候。雖然send()方法會馬上執(zhí)行,但數(shù)據(jù)并不是馬上傳輸。瀏覽器會緩存應(yīng)用流出的數(shù)據(jù),你可以使用bufferedAmount屬性檢查已經(jīng)進入隊列但還未被傳輸?shù)臄?shù)據(jù)大小。這個值不包含協(xié)議框架、操作系統(tǒng)緩存和網(wǎng)絡(luò)軟件的開銷。
下面這個例子展示了如何使用bufferedAmount屬性每秒更新發(fā)送。如果網(wǎng)絡(luò)不能處理這個頻率,它會自適應(yīng)。
var THRESHOLD = 10240;
//建立連接
var ws = new WebSocket("ws://echo.websocket.org");
// Listen for the opening event
ws.onopen = function () {
setInterval( function() {
//緩存未滿的時候發(fā)送
if (ws.bufferedAmount < THRESHOLD) {
ws.send(getApplicationState());
}
}, 1000);
};
//使用bufferedAmount屬性發(fā)送數(shù)據(jù)可以避免網(wǎng)絡(luò)飽和。
3.protocol
在構(gòu)造函數(shù)中,protocol參數(shù)讓服務(wù)端知道客戶端使用的WebSocket協(xié)議。而WebSocket對象的這個屬性就是指的最終服務(wù)端確定下來的協(xié)議名稱,當服務(wù)端沒有選擇客戶端提供的協(xié)議或者在連接握手結(jié)束之前,這個屬性都是空的。
完整實例:
現(xiàn)在我們已經(jīng)過了一遍WebSocket的構(gòu)造函數(shù)、事件、屬性和方法,接下來通過一個完整的實例來學習WebSocket API。實例使用“Echo”服務(wù)器:ws://echo.websocket.org,它能夠接受和返回發(fā)過去的數(shù)據(jù)。這樣有助于理解WebSocket API是如何和服務(wù)器交互的。
首先,我們先建立連接,讓頁面展示客戶端連接服務(wù)端的信息,然后發(fā)送、接受消息,最后關(guān)閉連接。
Websocket Echo Client
function setup() {
output = document.getElementById("output");
ws = new WebSocket("ws://echo.websocket.org/echo");
// 監(jiān)聽open
ws.onopen = function (e) {
log("Connected");
sendMessage("Hello WebSocket!");
}
// 監(jiān)聽close
ws.onclose = function (e) {
log("Disconnected: " + e.reason);
}
//監(jiān)聽errors
ws.onerror = function (e) {
log("Error ");
}
// 監(jiān)聽 messages
ws.onmessage = function (e) {
log("Message received: " + e.data);
//收到消息后關(guān)閉
ws.close();
}
}
// 發(fā)送消息
function sendMessage(msg) {
ws.send(msg);
log("Message sent");
}
// logging
function log(s) {
var p = document.createElement("p");
p.style.wordWrap = "break-word";
p.textContent = s;
output.appendChild(p);
// Also log information on the javascript console
console.log(s);
}
// Start
setup();
判斷瀏覽器是否支持:
console.log("This browser supports WebSocket!");
} else {
console.log("This browser does not support WebSocket.");
}
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
8958瀏覽量
85081 -
瀏覽器
+關(guān)注
關(guān)注
1文章
1009瀏覽量
35226 -
WebSocket
+關(guān)注
關(guān)注
0文章
28瀏覽量
3725
發(fā)布評論請先 登錄
相關(guān)推薦
評論