<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## ## 一、為什么需要 WebSocket? 初次接觸 WebSocket 的人,都會問同樣的問題:我們已經有了 HTTP 協議,為什么還需要另一個協議?它能帶來什么好處? 答案很簡單,因為 HTTP 協議有一個缺陷:通信只能由客戶端發起。 舉例來說,我們想了解今天的天氣,只能是客戶端向服務器發出請求,服務器返回查詢結果。HTTP 協議做不到服務器主動向客戶端推送信息。 這種單向請求的特點,注定了如果服務器有連續的狀態變化,客戶端要獲知就非常麻煩。我們只能使用["輪詢"](https://www.pubnub.com/blog/2014-12-01-http-long-polling/):每隔一段時候,就發出一個詢問,了解服務器有沒有新的信息。最典型的場景就是聊天室。 輪詢的效率低,非常浪費資源(因為必須不停連接,或者 HTTP 連接始終打開)。因此,工程師們一直在思考,有沒有更好的方法。WebSocket 就是這樣發明的。 ## 二、簡介 WebSocket 協議在2008年誕生,2011年成為國際標準。所有瀏覽器都已經支持了。 它的最大特點就是,服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話,屬于[服務器推送技術](https://en.wikipedia.org/wiki/Push_technology)的一種。 ![](http://www.ruanyifeng.com/blogimg/asset/2017/bg2017051502.png) 其他特點包括: (1)建立在 TCP 協議之上,服務器端的實現比較容易。 (2)與 HTTP 協議有著良好的兼容性。默認端口也是80和443,并且握手階段采用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理服務器。 (3)數據格式比較輕量,性能開銷小,通信高效。 (4)可以發送文本,也可以發送二進制數據。 (5)沒有同源限制,客戶端可以與任意服務器通信。 (6)協議標識符是`ws`(如果加密,則為`wss`),服務器網址就是 URL。 > ~~~markup > > ws://example.com:80/some/path > > ~~~ ![](http://www.ruanyifeng.com/blogimg/asset/2017/bg2017051503.jpg) **長連接**:一個連接上可以連續發送多個數據包,在連接期間,如果沒有數據包發送,需要雙方發鏈路檢查包。 **TCP/IP**:TCP/IP屬于傳輸層,主要解決數據在網絡中的傳輸問題,只管傳輸數據。但是那樣對傳輸的數據沒有一個規范的封裝、解析等處理,使得傳輸的數據就很難識別,所以才有了應用層協議對數據的封裝、解析等,如HTTP協議。 **HTTP**:HTTP是應用層協議,封裝解析傳輸的數據。 從HTTP1.1開始其實就默認開啟了長連接,也就是請求header中看到的Connection:Keep-alive。但是這個長連接只是說保持了(服務器可以告訴客戶端保持時間Keep-Alive:timeout=200;max=20;)這個TCP通道,直接Request - Response,而不需要再創建一個連接通道,做到了一個性能優化。但是HTTP通訊本身還是Request - Response。 **socket**:與HTTP不一樣,socket不是協議,它是在程序層面上對傳輸層協議(可以主要理解為TCP/IP)的接口封裝。 我們知道傳輸層的協議,是解決數據在網絡中傳輸的,那么socket就是傳輸通道兩端的接口。所以對于前端而言,socket也可以簡單的理解為對TCP/IP的抽象協議。 **WebSocket**: WebSocket是包裝成了一個應用層協議作為socket,從而能夠讓客戶端和遠程服務端通過web建立全雙工通信。websocket提供ws和wss兩種URL方案。[協議英文文檔](https://tools.ietf.org/rfc/rfc6455.txt)和[中文翻譯](http://blog.csdn.net/stoneson/article/details/8063802) ## WebSocket API * * * 使用WebSocket構造函數創建一個WebSocket連接,返回一個websocket實例。通過這個實例我們可以監聽事件,這些事件可以知道什么時候簡歷連接,什么時候有消息被推過來了,什么時候發生錯誤了,時候連接關閉。我們可以使用node搭建一個WebSocket服務器來看看,[github](https://github.com/daipeng7/websocket)。同樣也可以調用[websocket.org](http://demos.kaazing.com/echo/)網站的demo服務器[demos.kaazing.com/echo/](http://demos.kaazing.com/echo/)。 ### 事件 ~~~ //創建WebSocket實例,可以使用ws和wss。第二個參數可以選填自定義協議,如果多協議,可以以數組方式 var socket = new WebSocket('ws://demos.kaazing.com/echo'); 復制代碼 ~~~ * **open** 服務器相應WebSocket連接請求觸發 ~~~ socket.onopen = (event) => { socket.send('Hello Server!'); }; 復制代碼 ~~~ * **message** 服務器有 響應數據 觸發 ~~~ socket.onmessage = (event) => { debugger; console.log(event.data); }; 復制代碼 ~~~ * **error** 出錯時觸發,并且會關閉連接。這時可以根據錯誤信息進行按需處理 ~~~ socket.onerror = (event) => { console.log('error'); } 復制代碼 ~~~ * **close** ~~~ 連接關閉時觸發,這在兩端都可以關閉。另外如果連接失敗也是會觸發的。 針對關閉一般我們會做一些異常處理,關于異常參數: 1. socket.readyState 2 正在關閉 3 已經關閉 2. event.wasClean [Boolean] true 客戶端或者服務器端調用close主動關閉 false 反之 3. event.code [Number] 關閉連接的狀態碼。socket.close(code, reason) 4. event.reason [String] 關閉連接的原因。socket.close(code, reason) socket.onclose = (event) => { debugger; } 復制代碼 ~~~ ### 方法 * **send** send(data) 發送方法 data 可以是String/Blob/ArrayBuffer/ByteBuffer等 需要注意,使用send發送數據,必須是連接建立之后。一般會在onopen事件觸發后發送: ~~~ socket.onopen = (event) => { socket.send('Hello Server!'); }; 復制代碼 ~~~ 如果是需要去響應別的事件再發送消息,也就是將WebSocket實例socket交給別的方法使用,因為在發送時你不一定知道socket是否還連接著,所以可以檢查readyState屬性的值是否等于OPEN常量,也就是查看socket是否還連接著。 ~~~ btn.onclick = function startSocket(){ //判斷是否連接是否還存在 if(socket.readyState == WebSocket.OPEN){ var message = document.getElementById("message").value; if(message != "") socket.send(message); } } 復制代碼 ~~~ * **close** 使用close(\[code\[,reason\]\])方法可以關閉連接。code和reason均為選填 ~~~ // 正常關閉 socket.close(1000, "closing normally"); 復制代碼 ~~~ ### 常量 | 常量名 | 值 | 描述 | | --- | --- | --- | | CONNECTING | 0 | 連接還未開啟 | | OPEN | 1 | 連接開啟可以通信 | | CLOSING | 2 | 連接正在關閉中 | | CLOSED | 3 | 連接已經關閉 |
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看