小結: 客戶端和瀏覽器"實時通訊"

olddoor:  經過本文可瞭解客戶端和瀏覽器"實時通訊"的解決方案
1 定時輪詢(拉取)
    1.1 定時輪詢, 整個頁面刷新(過期)
    1.2 基於js, 定時輪詢(普通輪詢)
    1.3 基於js, 長輪詢等Comet類風格的請求.(客戶端請求後服務器端有結果反饋, 沒結果hold請求, 等有結果或超時再響應. 獲得響應後客戶端從新發起輪詢請求.  此方式對比普通輪詢,減小js請求服務器端的次數(減小建立鏈接的開銷))
服務器端的早期實現方式可在servet中for循環等待有結果再response.
servet3.0開始 相關開發規範支持異步處理的特性.  對應服務器端可基於sevlet3的規範(服務器一側接收請求的線程和處理請求的線程分開, 接收請求後容器線程處理其餘請求, 原請求的鏈接不關閉, 待處理線程處理完畢後, 經過監聽器等方式經過原未關閉的鏈接給與客戶端響應.)

2 相互通訊(推送, 如websocket爲表明)


1 請求-響應的侷限性

網絡上的客戶端-服務器通訊在過去曾是一種請求-響應模型,要求客戶端(好比 Web 瀏覽器)向服務器請求資源。服務器經過發送所請求的資源來響應客戶端請求。若是資源不可用,或者客戶端沒有權限訪問它,那麼服務器會發送一條錯誤消息。在請求-響應架構中,未經請求, 服務器毫不能主動向客戶端發送未經請求的消息

2 瀏覽器和服務器實時通訊的解決方案

瀏覽器須要和服務器保持實時通訊效果實現的一些想法, 思路其實無非就是兩種
1 客戶端定時到服務器查詢信息, 實現一種看起來是"服務器推送"的效果.
2 服務器和客戶端實時通訊, 雙方能互相推送信息.

對應的技術實現上可能的方案有:
1 基於客戶端Socket的技術(過期的解決方案, 表明方案Flash XMLSocket,Java Applet套接口,Activex包裝的socket ) 
  • 優勢:原生socket的支持,和PC端和移動端的實現方式類似;
  • 缺點:瀏覽器端須要裝相應的插件;
2 傳統的輪詢方式: 利用js定時輪詢服務器. 客戶端每隔一段時間都會向服務器請求新數據. 要想取得數據,必須首先發送請求. 性能差.不推薦
3 Comet技術 (能夠理解爲一種技術分類. 服務器在沒有新數據的時候再也不返回空響應,而是hold住鏈接. 
並且把鏈接保持到有服務器方有更新的時候或超時(設置)才返回響應信息並關閉鏈接,客戶端處理完響應信息後再向服務器發送新的請求的這類實現技術. 稱爲Comet技術 )
本質是基於HTTP長鏈接定時"拉數據" 達到一個瀏覽器和服務器實時通訊, 貌似"服務器推"的效果.
Comet是一種技術思路, 表明的實現方案有 長輪詢和 基於 Iframe 及流(streaming)方式.

4 HTML5 標準的WebSocket 和Server-sent-events(SSE)
5 自建或者使用第三方雲推送(本質和上述3種已發生改變, 我方已變成推送接收方)

本文不涉及App或者小程序之類的推送. 


3 輪詢

無論服務端數據有無更新,客戶端每隔定長時間請求拉取一次數據,可能有更新數據返回,也可能什麼都沒有。
這顯然這不會是"實時通訊"/"服務器推"效果可能的選擇方案.
實現通常用AJAX 定時(可使用JS的 setTimeout 函數)去服務器查詢是否有新消息 。這讓用戶感受應用是實時的。實際上這會形成延時和性能問題,由於服務器每秒都要處理大量的鏈接請求,每次請求都會有 TCP 三次握手並附帶 HTTP 的頭信息。儘管如今不少應用仍在使用輪詢,但這並非理想的解決方案。
  • 優勢:服務端邏輯簡單;
  • 缺點:大多數請求是無效請求,在輪詢很頻繁的狀況下對服務器的壓力很大;
可能的實現代碼, 利用XHR,經過setInterval定時發送請求,但會形成數據同步不及時及無效的請求,增長後端處理壓力。
function ajax(data){
    var xhr = new XMLHttpRequest();
    xhr.open('get', '/cgi-bin/xxx', true);
    xhr.onreadystatechange = function(){
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                ......
            }
        }
    }
    xhr.send(data);
}
setTimeout(function(){ajax({"data":"hehe"});}, 2000);//每隔2秒請求一次

4 comet 技術模型

Comet是技術實現的一個分類而已. 也可理解爲客戶端所須要的響應信息再也不須要主動地去索取,而是在服務器端以事件(Event)的形式推至客戶端的技術類別.
具體實現方式爲長輪詢和iframe流.

4.1 長輪詢

長輪詢是在Ajax傳統輪詢基礎上作的一些改進,服務器在沒有新數據的時候再也不返回空響應,而是hold住鏈接. 
並且把鏈接保持到有服務器方有更新的時候或超時(設置)才返回響應信息並關閉鏈接,客戶端處理完響應信息後再次向服務器發送新的請求。 (這種實現思路,這類方案被成爲Comet技術)
長輪詢的效果是讓 HTTP的鏈接保持,服務器端會阻塞請求,直到服務器端有一個事件觸發或者到達超時。客戶端在收到響應後再次發出請求,從新創建鏈接。
----------延伸--------------
前面提到長輪詢若是當時服務端沒有須要的相關數據,此時請求會hold住,直到服務端把相關數據準備好,或者等待必定時間直到這次請求超時,這裏你們是否有疑問,爲何不是一直等待到服務端數據準備好再返回,這樣也不須要再次發起下一次的 長輪詢 ,節省資源?
主要緣由是網絡傳輸層主要走的是tcp協議,tcp協議是可靠面向鏈接的協議,經過三次握手創建鏈接。可是所創建的鏈接是虛擬的,可能存在某段時間網絡不通,或者服務端程序非正常關閉,亦或服務端機器非正常關機,面對這些狀況客戶端根本不知道服務端此時已經不能互通,還在傻傻的等服務端發數據過來,而這一等通常都是很長時間。固然tcp協議棧在實現上有保活計時器來保證的,可是等到保活計時器發現鏈接已經斷開須要很長時間,若是沒有專門配置過相關的tcp參數,通常須要2個小時,並且這些參數是機器操做系統層面,因此,以此方式來保活不太靠譜,故 長輪詢 的實現上通常是須要設置超時時間的。
-----------------------------

如圖4-1, 從瀏覽器的角度來看,長輪詢的辦法保持了有效的請求,又避免了大量無效請求,而且即時性更好,這是一種可行的方案。

  • 優勢:任意瀏覽器均可用;實時性好,無消息的狀況下不會進行頻繁的請求;
  • 缺點:鏈接建立銷燬操做仍是比較頻繁,服務器維持着鏈接比較消耗資源;

在長輪詢方式下,客戶端是在 XMLHttpRequest 的 readystate 爲 4(即數據傳輸結束)時調用回調函數,進行信息處理。當 readystate 爲 4 時,數據傳輸結束,鏈接已經關閉。

4.1.1 短輪詢和長輪詢的區別

短輪詢中服務器對請求當即響應,而長輪詢中服務器等待新的數據到來才響應,所以實現了服務器向頁面推送實時,並減小了頁面的請求次數。
普通Ajax輪詢與基於Ajax的長輪詢原理對比: 圖4-2




4.1.2 長輪詢的編碼實現

可能的實現代碼:

JS客戶端

function longPoll(data, cbk){
    var xhr = new XMLHttpRequest();
    var url = '/cgi-bin/xxx';
    xhr.onreadystatechange = function(){
        if (xhr.readyState == 4) {//XMLHttpRequest 的狀態中4: 請求已完成,且響應已就緒
            if (xhr.status == 200) { //請求完畢後從新發起新的一次鏈接
                cbk(xhr.responseText);
                xhr.open('get', url, true);
                xhr.send(otherData);
            }
        }
    }
    xhr.open('get', url, true);
    xhr.send(data);
}
注意:
不管是輪詢仍是Comet技術, 思路都是客戶端頻繁間隔的對服務器端發送請求數據達到"服務器推"的效果, 會在服務端和客戶端都須要維持一個比較長時間的鏈接狀態,這一點在客戶端不算什麼太大的負擔,可是服務端是要同時對多個客戶端服務的,按照經典 Request-Response 交互模型,每個請求都佔用一個 Web 線程不釋放的話,Web 容器的線程則會很快消耗殆盡,而這些線程大部分時間處於空閒等待的狀態。
Comet對比輪詢只不過是在請求服務器的頻率上會大幅下降而已. 
而服務器一方 線程大部分時間處於空閒等待, 嚴重影響服務器性能(請求始終佔用鏈接) , 因此可以有異步處理的緣由,但願 Web 線程不須要同步的、一對一的處理客戶端請求,能作到一個 Web 線程處理多個客戶端請求。
服務器端可以異步處理請求的規範以及標準就是 Servlet3.0規範 引入的異步支持.

---------------延伸開始----------------------------
Servlet 3.0 做爲 Java EE 6 規範體系中一員,隨着 Java EE 6 規範一塊兒發佈。(Tomcat7提供了對Java EE6規範的支持。)
新特性部分列列舉以下:
1 異步處理支持:有了該特性,Servlet 線程再也不須要一直阻塞,直到業務處理完畢才能再輸出響應,最後才結束該 Servlet 線程。在接收到請求以後,Servlet 線程能夠將耗時的操做委派給另外一個線程來完成,本身在不生成響應的狀況下返回至容器。針對業務處理較耗時的狀況,這將大大減小服務器資源的佔用,而且提升併發處理速度。
2 新增的註解支持:該版本新增了若干註解,用於簡化 Servlet、過濾器(Filter)和監聽器(Listener)的聲明,這使得 web.xml 部署描述文件從該版本開始再也不是必選的了。
使用異步處理 Servlet 線程再也不是一直處於阻塞狀態以等待業務邏輯的處理,而是啓動異步線程以後能夠當即返回.
異步處理特性能夠應用於 Servlet 和過濾器兩種組件. 
1)對於使用傳統的部署描述文件 (web.xml) 配置 Servlet 和過濾器的狀況Servlet 3.0 爲 和 標籤增長了 子標籤,該標籤的默認取值爲 false,要啓用異步處理支持,則將其設爲 true 便可。以 Servlet 爲例
<servlet> 
    <servlet-name>DemoServlet</servlet-name> 
    <servlet-class>footmark.servlet.Demo Servlet</servlet-class> 
    <async-supported>true</async-supported> 
</servlet>
2) 使用註解方式: Servlet 3.0 提供的 @WebServlet 和 @WebFilter 進行 Servlet 或過濾器配置的狀況,這兩個註解都提供了 asyncSupported 屬性,默認該屬性的取值爲 false,要啓用異步處理支持,只需將該屬性設置爲 true 便可
@WebFilter 爲例,其配置方式以下所示:
@WebFilter(urlPatterns = 「/demo」,asyncSupported = true)
二、 Servlet 3.0 還爲異步處理提供了一個監聽器 ,使用  AsyncListener  接口表示.
異步的攔截器:
            1)、原生API的AsyncListener (使用異步servlet的時候須要註冊 AsyncListener )
            2)、SpringMVC:實現AsyncHandlerInterceptor
---------------延伸結束------------------- ---------


服務器端

(1)服務端基於servlet(同步/異步)的實現
詳見   Long Polling長輪詢及例子詳解  (名詞解釋, 例子服務端主要是 基於servlet的實現 )或者見( https://www.jianshu.com/p/d3f66b1eb748  和

服務器端異步實現
須要作的是
保證 web.xml 中application的配置的版本是3.0
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
能夠經過web.xml中的子元素<async-supported>true</async-supported>使得DispatcherServlet支持異步.此外的任何Filter參與異步語法處理必須配置爲支持ASYNC分派器類型。這樣能夠確保Spring Framework提供的全部filter都可以異步分發.自從它們繼承了OncePerRequestFilter以後.而且在runtime的時候會check filter是否須要被異步調用分發.
下面是web.xml的配置示例:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
            http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <filter>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.~.OpenEntityManagerInViewFilter</filter-class>
        <async-supported>true</async-supported>
    </filter>

    <filter-mapping>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ASYNC</dispatcher>
    </filter-mapping>

</web-app>
若是使用Sevlet3,Java配置能夠經過 WebApplicationInitializer ,你一樣須要像在 web.xml 中同樣,設置」asyncSupported」標籤爲ASYNC.爲了簡化這個配置,考慮繼承 AbstractDispatcherServletInitializer 或者 AbstractAnnotationConfigDispatcherServletInitializer 。它們會自動設置這些選項,使它很容易註冊過濾器實例。

在代碼層面:
接受處理請求的servlet須要使用Servlet 3.0爲異步處理提供了一個監聽器,使用AsyncListener接口表示。此接口負責管理異步事件.
Long Polling長輪詢及例子詳解例子中使用異步servlet處理請求, 就用到了 AsyncListener

見代碼片斷
asyncContext.addListener(new AsyncListener() { //這裏爲異步處理提供了一個監聽器,使用AsyncListener接口表示。此接口負責管理異步事件
            @Override
            public void onComplete(AsyncEvent event) throws IOException {

            }

            //超時處理,注意asyncContext.complete();,表示請求處理完成
            @Override
            public void onTimeout(AsyncEvent event) throws IOException {
                AsyncContext asyncContext = event.getAsyncContext();
                asyncContext.complete();
            }

            @Override
            public void onError(AsyncEvent event) throws IOException {

            }

            @Override
            public void onStartAsync(AsyncEvent event) throws IOException {

            }
        });

(2)服務器端基於SpringMVC實現(DeferredResult 或 Callable)
官方文檔中說DeferredResult和Callable( java.util.concurrent.Callable  涉及java多線程知識) )都是爲了異步生成返回值提供基本的支持。簡單來講就是一個請求進來,若是你使用了DeferredResult或者Callable,在沒有獲得返回數據以前DispatcherServlet和全部Filter就會退出Servlet容器線程但響應保持打開狀態,一旦返回數據有了,這個DispatcherServlet就會被再次調用而且處理,以異步產生的方式,向請求端返回值。 
這麼作的好處就是請求不會長時間佔用服務鏈接池,提升服務器的吞吐量。
這其實也就是SpringMVC對於外部請求的異步處理( 基本實現 Servlet 3.0的異步處理規範).核心是爲了提升減小http請求的鏈接的佔用, 接受請求後快速釋放, 將業務邏輯交給其餘線程處理. 業務邏輯處理完畢後從新拿到http請求鏈接, 由http鏈接返回給客戶端. 達到異步的效果.  

C ontroller中構造 Callable並將其做爲返回值. 
使用Callable大體流程說明
客戶端請求服務後;
  • SpringMVC調用Controller,Controller返回一個Callback對象
  • SpringMVC調用ruquest.startAsync而且將Callback提交到TaskExecutor使用一個隔離的線程去進行執行
  • DispatcherServlet以及Filters等從應用服務器線程中結束,但Response仍舊是打開狀態,也就是說暫時還不返回給客戶端
  • TaskExecutor調用Callback返回一個結果,SpringMVC將請求發送給應用服務器繼續處理
  • DispatcherServlet再次被調用而且繼續處理Callback返回的對象,根據Callable返回的結果。SpringMVC繼續進行視圖渲染流程等, 最終將其返回給客戶端

簡易流程參考如圖4-1-2

這裏寫圖片描述

DeferredResult
DeferredResult的處理過程與Callback相似,不同的地方在於它的結果不是DeferredResult直接返回的,而是由其它線程經過同步的方式設置到該對象中。
它的執行過程以下所示:

DeferredResult的處理順序與Callable十分類似,由應用程序多線程產生異步結果:javascript

  1. Controller返回一個DeferredResult對象,而且把它保存在內在隊列當中或者能夠訪問它的列表中。
  2. Spring MVC開始異步處理.
  3. DispatcherServlet與全部的Filter的Servlet容器線程退出,但Response仍然開放。
  4. application經過多線程返回DeferredResult中sets值.而且Spring MVC分發request給Servlet容器.
  5. DispatcherServlet再次被調用而且繼續異步的處理產生的結果.

爲進一步在異步請求處理動機的背景,而且when或者why使用它請看 this blog post series .
異步請求的異常處理 HTTP Streaming等略. 詳見http://www.javashuo.com/article/p-tgwlbeeu-dg.html (推薦)

SpringMVC的配置

Spring MVC提供Java Config與MVC namespace做爲選擇用來配置處理異步request.WebMvcConfigurer能夠經過configureAsyncSupport來進行配置,而xml能夠經過子元素來進行配置.html

若是你不想依賴Servlet容器(e.g. Tomcat是10)配置的值,容許你配置異步請求默認的timeout值。你能夠配置AsyncTaskExecutor用來包含Callable實例做爲controller方法的返回值.強烈建議配置這個屬性,由於在默認狀況下Spring MVC使用SimpleAsyncTaskExecutor。Spring MVC中Java配置與namespace容許你註冊CallableProcessingInterceptorDeferredResultProcessingInterceptor實例.前端

若是你想覆蓋DeferredResult的默認過時時間,你能夠選擇使用合適的構造器.一樣的,對於Callable,你能夠經過WebAsyncTask來包裝它而且使用相應的構造器來定製化過時時間.WebAsyncTask的構造器一樣容許你提供一個AsyncTaskExecutor.html5

原文地址:spring-framework-reference-4.2.6.RELEASEjava




4.2 iframe流(永久幀)

iframe方式是在頁面中插入一個隱藏的iframe,利用其src屬性在服務器和客戶端之間建立一條長鏈接,服務器向iframe傳輸數據(一般是HTML,內有負責插入信息的javascript),來實時更新頁面.
function foreverFrame(url,callback){
      var iframe = body.appendChild(document.createElement("iframe"));
      iframe.style.display="none";
      iframe.src=url+"?callback=parent.foreverFrame.callback";
      this.callback = callback;
    }
只不過這裏涉及父子iframe之間的通訊,要注意跨域問題。關於iframe跨域問題,隔壁團隊有個不錯的實現方案。 見http://www.alloyteam.com/2013/11/the-second-version-universal-solution-iframe-cross-domain-communication/ 
而後服務器就發送一堆消息到iframe中
<script>
parent.foreverFrame.callback('hello world!');
</script>
<script>
parent.foreverFrame.callback('hello Mars!');
</script>

4.3 流(xhr流)

具體解決方案有XHR 流(xhr-multipart)、htmlfile
xhr流(XMLHttpRequest Streaming)也是經過標準的XMLHttpRequest對象得到的,可是須要在readyState爲3的時候去訪問數據,這樣就沒必要等待鏈接關閉以後再操做數據。
參考代碼
function xhrStreaming(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('post', url, true);
    //保存上次返回的文檔位置
    var lastSize;
    xhr.onreadystatechange = function() {
        var newResponseText = "";
        if (xhr.readyState > 2) { 
            newResponseText = xhr.responseText.slice(lastSize);
            lastSize = xhr.responseText.length;
            callback(newResponseText);
        }
        if (xhr.readyState == 4) {
            xhrStreaming(url, callback);
        }
    }
    xhr.send(null);
}
其實跟永久幀的方法也相似,只不過是把iframe獲取內容的方式改爲了ajax,而後在xhr內部處理增量邏輯、回調和重發。
這裏須要注意的是連接時間須要有超時限制,不然內存性能會受到影響,另外單個請求返回數據須要限定長度,不能無限增大。

注意:
無論是長輪詢仍是流,請求都須要在服務器上存在一段較長時間,所以Comet被稱爲"基於HTTP長鏈接的服務器推技術"。這打破了每一個請求一個線程的模型。這個模型顯然對Comet不適用。因此服務端這邊Java對此提出了非阻塞IO(non-blocking IO)解決方案, Java 經過它的NIO庫提供非阻塞IO處理Comet。
Tomcat配置server.xml, 即啓用異步版本的IO鏈接器
protocol="org.apache.coyote.http11.Http11NioProtocol"
後臺請求處理以servlet爲例, 經過 servlet 實現 CometProcessor 接口。這個接口要求實現 event() 方法,在配置的 Http11NioProtocol 調用 event() 方法來處理請求,而不是 doGet 或 doPost。
服務器端代碼實現略.

WebSocket 



Ajax
WebSocket是html5規範新引入的功能 是基於 TCP 的雙向的、全雙工的 socket 鏈接。(是獨立的、建立在 TCP 上的協議。).
WebSocket 用於解決瀏覽器與後臺服務器雙向通信的問題,使用WebSocket技術,後臺能夠隨時向前端推送消息,以保證先後臺狀態統一,在傳統的無狀態HTTP協議中,這是「沒法作到」的。在WebSocke推出之前,服務端向客戶端推送消息的方式都以曲線救國的輪詢方式(  Comet 或輪詢 )爲主。


WebSocket不屬於http無狀態協議,協議名爲」ws」,這意味着一個websocket鏈接地址會是這樣的寫法:ws://twaver.com:8080/webSocketServer。ws不是http,因此傳統的web服務器不必定支持,須要服務器與瀏覽器同時支持, WebSocket才能正常運行,目前的支持還不廣泛,須要特別的web服務器和現代的瀏覽器。

如今咱們來看一下都有哪些瀏覽器支持 WebSocket:
Chrome >= 4
Safari >= 5
iOS >= 4.2
Firefox >= 4*
Opera >= 11*
檢測瀏覽器是否支持 WebSocket 也很是簡單、直接:
var supported = ("WebSocket" in window);
if (supported) alert("WebSockets are supported");
Websocket 經過 HTTP/1.1 協議的101狀態碼進行握手。爲了建立Websocket鏈接,須要經過瀏覽器發出請求,以後服務器進行迴應,這個過程一般稱爲「握手」(handshaking)。

利用HTTP完成握手有幾個好處。首先,讓WebSockets與現有HTTP基礎設施兼容:WebSocket服務器能夠運行在80和443 端口上,這一般是對客戶端惟一開放的端口。其次,讓咱們能夠重用並擴展HTTP的Upgrade流,爲其添加自定義的WebSocket首部,以完成協商。

5.1 WebSocket API

瀏覽器提供的WebSocket API很簡單,使用時無需關心鏈接管理和消息處理等底層細節,只須要發起鏈接,綁定相應的事件回調便可。

var connection = new WebSocket('ws://localhost:8080');
// When the connection is open, send some data to the server connection.onopen = function () { connection.send('Ping'); // Send the message 'Ping' to the server }; // Log errors connection.onerror = function (error) { console.log('WebSocket Error ' + error); }; // Log messages from the server connection.onmessage = function (e) { console.log('Server: ' + e.data); };
WebSocket資源URL採用了自定議模式,沒有使用http是爲了在非http協議場景下也能使用,wss表示使用加密信道通訊(TCP + TLS),支持接收和發送文本和二進制數據。
請求頭信息
Connection:Upgrade Sec-WebSocket-Key:eDCPPyPQZq7PiwRcx8SPog== Sec-WebSocket-Version:13 Upgrade:websocket
響應頭信息
HTTP/1.1 101 Switching Protocols
Upgrade:websocket
Connection:upgrade
Sec-WebSocket-Accept:QJsTRym36zHnArQ7FCmSdPhuK78=

// Connection:upgrade 升級被服務器贊成
// Upgrade:websocket 指示客戶端升級到websocket
// Sec-WebSocket-Accept:參考上面請求的Sec-WebSocket-Key的註釋
最後,前述握手完成後,若是握手成功,該鏈接就能夠用做雙向通訊信道交換WebSocket消息。到此,客戶端與服務器之間不會再發生HTTP通訊,一切由WebSocket 協議接管。

使用場景
適合於對數據的實時性要求比較強的場景,如通訊、股票、Feed、直播、共享桌面,特別適合於客戶端與服務頻繁交互的狀況下,如實時共享、多人協做等平臺。

優勢
  • 真正的全雙工通訊
  • 支持跨域設置(Access-Control-Allow-Origin)
缺點
  • 採用新的協議,後端須要單獨實現
  • 客戶端並非全部瀏覽器都支持
  • 代理服務器會有不支持websocket的狀況
  • 無超時處理
  • 更耗電及佔用資源

TIP 代理、不少現有的HTTP中間設備可能不理解新的WebSocket協議,而這可能致使各類問題,使用時須要注意,可使藉助TLS,經過創建一條端到端的加密信道,可讓WebSocket通訊繞過全部中間代理。

5.2 WebSocket在Java中

JavaEE 7的JSR-356:Java API for WebSocket,已經對WebSocket作了支持。很多Web容器,如Tomcat、Jetty等都支持WebSocket。Tomcat從7.0.27開始支持WebSocket,從7.0.47開始支持JSR-356。

待續




SSE

待續

參考
相關文章
相關標籤/搜索