1. 程式人生 > >webSocket應用:同步html5畫布

webSocket應用:同步html5畫布

本教程演示瞭如何建立簡單 Web 應用程式,以在連線到單個伺服器應用程式的客戶端瀏覽器之間實現協作。當用戶在客戶端瀏覽器中的畫布上繪製圖形元素時,該元素將顯示在所有已連線客戶端的畫布上。如何工作?當瀏覽器載入 Web 頁時,客戶端指令碼將嚮應用程式伺服器傳送 WebSocket 握手請求。應用程式可以從會話中連線的客戶端接受 JSON 和二進位制訊息,並將訊息廣播到連線的所有客戶端。

在本教程中,您將建立一個 Web 應用程式,該應用程式使用用於 WebSocket 的 Java API (JSR 356),從而支援瀏覽器客戶端與應用程式伺服器之間的雙向通訊。用於 WebSocket 的 Java API 支援建立 WebSocket Java 元件,啟動和攔截 WebSocket 事件,以及建立和使用 WebSocket 文字和二進位制訊息。本教程還將演示如何使用用於 JSON 處理的 Java API (

JSR 353) 以生成和使用 JSON。用於 WebSocket 的 Java API 和用於 JSON 處理的 Java API 是 Java EE 7 平臺的組成部分 (JSR 342)。

應用程式中包含一個 WebSocket 端點和一些解碼器和編碼器介面、一個 Web 頁和一些 JavaScript 檔案,載入 Web 頁時或從 Web 頁中的窗體呼叫時,這些 JavaScript 檔案將執行在客戶端瀏覽器中。將應用程式部署到 GlassFish Server Open Source Edition 4(Java EE 7 技術的引用實現)。

教程練習

此頁上的內容適用於 NetBeans IDE 7.3、7.4 和 8.0

要學習本教程,您需要具備以下軟體和資源。

注:GlassFish 4 隨 NetBeans IDE 的 Java EE 下載包捆綁提供。

先決條件

本文件假定您具備以下技術的一些基本知識或程式設計經驗:

  • Java 程式設計
  • JavaScript/HTML 程式設計
  • NetBeans IDE

在開始本教程之前,您可以先閱讀下面這些文件。

建立 Web 應用程式專案

本練習的目標是使用 IDE 中的 "New Project"(新建專案)嚮導建立一個 Web 應用程式專案。建立該專案時,將選擇 Java EE 7 作為 Java EE 版本,並選擇 GlassFish 4 作為應用程式伺服器。GlassFish 4 是 Java EE 7 平臺的引用實現。您必須具有支援註冊到 IDE 的 Java EE 7 的應用程式伺服器才能在本教程中建立應用程式。

  1. 從主選單中選擇 "File"(檔案)> "New Project"(新建專案)(在 Windows 上為 Ctrl-Shift-N 組合鍵;在 Mac 上為 ⌘-Shift-N 組合鍵)。
  2. 從 "Maven" 類別中選擇 "Web Application"(Web 應用程式)。單擊 "Next"(下一步)。
  3. 鍵入 WhiteboardApp 作為專案名稱並設定專案位置。
  4. 鍵入 org.sample 作為組 ID。單擊 "Next"(下一步)。
  5. 選擇 GlassFish Server 4.0 作為伺服器。
  6. 將 Java EE 版本設定為 Java EE 7 Web。單擊 "Finish"(完成)。
    新建專案嚮導中的 "Project"(專案)詳細資訊

單擊 "Finish"(完成),此時 IDE 將建立專案並在 "Projects"(專案)視窗中開啟該專案。

建立 WebSocket 端點

在此部分,您將建立一個 WebSocket 端點類和一個 JavaScript 檔案。WebSocket 端點類包含一些在開啟會話時執行的基本方法。然後,將建立一個 JavaScript 檔案,在載入頁面時該檔案將啟動與伺服器的握手操作。隨後將執行應用程式以測試連線是否成功。

有關使用 WebSocket API 和標註的更多資訊,請參見 javax.websocket 包的概要。

建立端點

在此練習中,您將使用 IDE 中的嚮導幫助建立 WebSocket 端點類。

  1. 在 "Projects"(專案)視窗中右鍵單擊 "Source Packages"(源包)節點,然後選擇 "New"(新建)> "Other"(其他)。
  2. 在 "Web" 類別中選擇 "WebSocket Endpoint"(WebSocket 端點)。單擊 "Next"(下一步)。
  3. 鍵入 MyWhiteboard 作為類名。
  4. 在 "Package"(包)下拉列表中選擇 org.sample.whiteboardapp
  5. 鍵入 /whiteboardendpoint 作為 WebSocket URI。單擊 "Finish"(完成)。
    "New File"(新建檔案)嚮導中的 WebSocket 端點

    在單擊 "Finish"(完成)後,IDE 將生成 WebSocket 端點類,並在原始碼編輯器中開啟檔案。在編輯器中,您會看到 IDE 生成了一些屬於 WebSocket API 一部分的標註。使用  標註類以將類標識為端點,並將 WebSocket URI 指定為該標註的引數。IDE 還生成了一個使用 標註的預設 onMessage 方法。每次客戶端收到 WebSocket 訊息時都會呼叫使用 @OnMessage 標註的方法。

    @ServerEndpoint("/whiteboardendpoint")
    public class MyWhiteboard {
    
        @OnMessage
        public String onMessage(String message) {
            return null;
        }
        
    }
  6. 將以下欄位(粗體)新增到類中。
    @ServerEndpoint("/whiteboardendpoint")
    public class MyWhiteboard {
        private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
    
        @OnMessage
        public String onMessage(String message) {
            return null;
        }
    }
  7. 新增以下 onOpen 和 onClose 方法。
        @OnOpen
        public void onOpen (Session peer) {
            peers.add(peer);
        }
    
        @OnClose
        public void onClose (Session peer) {
            peers.remove(peer);
        }

    您會看到 onOpen 和 onClose 方法使用  和  WebSocket API 標註進行了標註。開啟 Web 套接字會話時會呼叫使用@OnOpen 進行標註的方法。在此示例中,標註的 onOpen 方法將瀏覽器客戶端新增到當前會話中的對等組中,而 onClose 方法則從組中刪除瀏覽器。

    使用原始碼編輯器中的提示和程式碼完成可幫助生成這些方法。單擊類宣告旁邊的左旁註中的提示圖示(或者將插入游標置於類宣告中並按下 Alt-Enter 組合鍵),然後在彈出選單中選擇相應方法。程式碼完成功能可幫助您對方法進行編碼。

    原始碼編輯器中的程式碼提示的螢幕快照
  8. 在編輯器中右鍵單擊,然後選擇 "Fix Imports"(修復匯入)(Alt-Shift-I 組合鍵;在 Mac 上為 ⌘-Shift-I 組合鍵)。儲存所做的更改。

    您將看到 javax.websocket 中類的 import 語句會新增到檔案中。

端點現已建立。現在,您需要建立 JavaScript 檔案以啟動 WebSocket 會話。

啟動 WebSocket 會話

在此練習中,您將建立一個 JavaScript 檔案以啟動 WebSocket 會話。瀏覽器客戶端通過 TCP 與伺服器進行 HTTP“握手”,從而加入會話。在 JavaScript 檔案中,將指定端點的 wsURI 的名稱並宣告 WebSocket。wsURI URI 方案是 WebSocket 協議的一部分,指定應用程式端點的路徑。

  1. 在專案視窗中,右鍵單擊專案節點,然後選擇 "New"(新建)> "Other"(其他)。
  2. 在 "New File"(新建檔案)嚮導的 "Web" 類別中選擇 "JavaScript File"(JavaScript 檔案)。單擊 "Next"(下一步)。
  3. 鍵入 websocket 作為 JavaScript 檔名。單擊 "Finish"(完成)。
  4. 將以下內容新增到 JavaScript 檔案中。
    var wsUri = "ws://" + document.location.host + document.location.pathname + "whiteboardendpoint";
    var websocket = new WebSocket(wsUri);
    
    websocket.onerror = function(evt) { onError(evt) };
    
    function onError(evt) {
        writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
    }

    當瀏覽器載入 websocket.js 時,此指令碼將啟動與伺服器的會話握手。

  5. 開啟 index.html,然後將以下程式碼(粗體)新增到檔案底部,以便在頁面完成載入時載入 websocket.js
    <body>
        <h1>Collaborative Whiteboard App</h1>
            
        <script type="text/javascript" src="websocket.js"></script>
    </body>

現在,您可以測試 WebSocket 端點是否正在工作,會話是否已啟動,以及客戶端是否已新增到會話中。

測試端點

在此練習中,您將向 JavaScript 檔案中新增一些簡單方法,以便在瀏覽器連線到端點時將 wsURI 輸出到瀏覽器視窗。

  1. 將以下 <div> 標記(粗體)新增到 index.html
    <h1>Collaborative Whiteboard App</h1>
            
    <div id="output"></div>
    <script type="text/javascript" src="websocket.js"></script>
  2. 將以下宣告和方法新增到 websocket.js。儲存所做的更改。
    // For testing purposes
    var output = document.getElementById("output");
    websocket.onopen = function(evt) { onOpen(evt) };
    
    function writeToScreen(message) {
        output.innerHTML += message + "<br>";
    }
    
    function onOpen() {
        writeToScreen("Connected to " + wsUri);
    }
    // End test functions

    當頁面載入 JavaScript 時,這些函式將輸出瀏覽器已連線到端點的訊息。在確認端點正確執行之後,可以刪除這些函式。

  3. 在 "Projects"(專案)視窗中右鍵單擊專案,然後選擇 "Run"(執行)。

執行應用程式時,IDE 將啟動 GlassFish Server,然後構建並部署應用程式。索引頁將在瀏覽器中開啟,並且您將會在瀏覽器視窗中看到以下訊息。

瀏覽器視窗中的已連線到端點的訊息

在瀏覽器視窗中,您會看到以下接受訊息的端點:http://localhost:8080/WhiteboardApp/whiteboardendpoint

建立白板

在此部分,您將建立類和 JavaScript 檔案以傳送和接收 JSON 文字訊息。您還將新增一個 HTML5 Canvas 元素(用於繪製和顯示一些內容)和一個含有單選按鈕的 HTML <form>(用於指定畫筆的形狀和顏色)。

將畫布新增到 Web 頁中

在此練習中,將向預設索引頁中新增 canvas 元素和 form 元素。窗體中的複選框確定畫布的畫筆屬性。

  1. 在原始碼編輯器中開啟 index.html
  2. 刪除您新增的 <div> 標記以測試端點,並在開始的 body 標記之後新增以下 <table> 和 <form> 元素(粗體)。
    <h1>Collaborative Whiteboard App</h1>
            
        <table>
            <tr>
                <td>
                </td>
                <td>
                    <form name="inputForm">
                        
    
                    </form>
                </td>
            </tr>
        </table>
        <script type="text/javascript" src="websocket.js"></script>
        </body>
  3. 為 canvas 元素新增以下程式碼(粗體)。
            <table>
                <tr>
                    <td>
                        <canvas id="myCanvas" width="150" height="150" style="border:1px solid #000000;"></canvas>
                    </td>
  4. 新增以下 <table> 以新增單選按鈕用於選擇顏色和形狀。儲存所做的更改。
            <table>
                <tr>
                    <td>
                        <canvas id="myCanvas" width="150" height="150" style="border:1px solid #000000;"></canvas>
                    </td>
                    <td>
                        <form name="inputForm">
                            <table>
    
                                <tr>
                                    <th>Color</th>
                                    <td><input type="radio" name="color" value="#FF0000" checked="true">Red</td>
                                    <td><input type="radio" name="color" value="#0000FF">Blue</td>
                                    <td><input type="radio" name="color" value="#FF9900">Orange</td>
                                    <td><input type="radio" name="color" value="#33CC33">Green</td>
                                </tr>
    
                                <tr>
                                    <th>Shape</th>
                                    <td><input type="radio" name="shape" value="square" checked="true">Square</td>
                                    <td><input type="radio" name="shape" value="circle">Circle</td>
                                    <td> </td>
                                    <td> </td>
                                </tr>
    
                            </table>
                        </form>

    畫布上繪製的任何圖形的形狀、顏色和座標都將轉換為 JSON 結構中的字串並作為訊息傳送至 WebSocket 端點。

建立 POJO

在此練習中,您將建立一個簡單的 POJO。

  1. 右鍵單擊專案節點,然後選擇 "New"(新建)> "Java Class"(Java 類)。
  2. 鍵入 Figure 作為類名,並從 "Package"(包)下拉列表中選擇 org.sample.whiteboardapp。單擊 "Finish"(完成)。
  3. 在原始碼編輯器中,新增以下內容(粗體):
    public class Figure {
        private JsonObject json;
    }

    新增程式碼時,系統將提示您為 javax.json.JsonObject 新增 import 語句。如果未進行提示,請按下 Alt-Enter 組合鍵。

    有關 javax.json.JsonObject 的更多資訊,請參見屬於 Java EE 7 規範一部分的用於 JSON 處理的 Java API (JSR 353)。

  4. 為 json 建立 getter 和 setter。

    可以在 "Insert Code"(插入程式碼)彈出選單中選擇 getter 和 setter(在 Windows 上為 Alt-Ins;在 Mac 上為 Ctrl-I),以便開啟 "Generate Getters and Setter"(生成 getter 和 setter)對話方塊。或者,也可以從主選單中選擇 "Source"(源)> "Insert Code"(插入程式碼)。

    &quot;Generate Getter and Setter&quot;(生成 getter 和 setter)對話方塊
  5. 為 json 新增建構函式。
        public Figure(JsonObject json) {
            this.json = json;
        }

    可以在 "Insert Code"(插入程式碼)彈出選單中選擇 "Constructor"(建構函式)(Ctrl-I 組合鍵)。

    &quot;Generate Constructor&quot;(生成建構函式)彈出選單
  6. 新增以下 toString 方法:
        @Override
        public String toString() {
            StringWriter writer = new StringWriter();
            Json.createWriter(writer).write(json);
            return writer.toString();
        }
  7. 在編輯器中右鍵單擊,然後選擇 "Fix Imports"(修復匯入)(Alt-Shift-I 組合鍵;在 Mac 上為 ⌘-Shift-I 組合鍵)。儲存所做的更改。

建立座標類

現在,將為畫布上繪製的圖形座標建立一個類。

  1. 右鍵單擊專案節點,然後選擇 "New"(新建)> "Java Class"(Java 類)。
  2. 在 "New Java Class"(新建 Java 類)嚮導中,鍵入 Coordinates 作為類名,然後在 "Package"(包)下拉列表中選擇org.sample.whiteboardapp。單擊 "Finish"(完成)。
  3. 在原始碼編輯器中,新增以下程式碼。儲存所做的更改。
        private float x;
        private float y;
    
        public Coordinates() {
        }
    
        public Coordinates(float x, float y) {
            this.x = x;
            this.y = y;
        }
    
        public float getX() {
            return x;
        }
    
        public void setX(float x) {
            this.x = x;
        }
    
        public float getY() {
            return y;
        }
    
        public void setY(float y) {
            this.y = y;
        }
                    

該類只包含 x 和 y 座標欄位以及某些 getter 和 setter。

生成 JSON 字串

在此練習中,您將建立一個 JavaScript 檔案,該檔案將 canvas 元素上繪製的圖形的詳細資訊放入傳送到 WebSocket 端點的 JSON 結構。

  1. 右鍵單擊專案節點,然後選擇 "New"(新建)> "JavaScript File"(JavaScript 檔案)以開啟 "New JavaScript File"(新建 JavaScript 檔案)嚮導。
  2. 鍵入 whiteboard 作為檔名。單擊 "Finish"(完成)。

    單擊 "Finish"(完成)後,IDE 將建立空 JavaScript 檔案並在編輯器中開啟該檔案。您可以在 "Projects"(專案)視窗中的 "Web Pages"(Web 頁)節點下看到該新檔案。

  3. 新增以下程式碼以初始化畫布並新增事件監聽程式。
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
    canvas.addEventListener("click", defineImage, false);

    您可以看到當用戶在 canvas 元素中單擊時呼叫了 defineImage 方法。

  4. 新增下面的 getCurrentPosdefineImage 和 drawImageText 方法以構造 JSON 結構並將其傳送到端點 (sendText(json))。
    function getCurrentPos(evt) {
        var rect = canvas.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };
    }
                
    function defineImage(evt) {
        var currentPos = getCurrentPos(evt);
        
        for (i = 0; i < document.inputForm.color.length; i++) {
            if (document.inputForm.color[i].checked) {
                var color = document.inputForm.color[i];
                break;
            }
        }
                
        for (i = 0; i < document.inputForm.shape.length; i++) {
            if (document.inputForm.shape[i].checked) {
                var shape = document.inputForm.shape[i];
                break;
            }
        }
        
        var json = JSON.stringify({
            "shape": shape.value,
            "color": color.value,
            "coords": {
                "x": currentPos.x,
                "y": currentPos.y
            }
        });
        drawImageText(json);
            sendText(json);
    }
    
    function drawImageText(image) {
        console.log("drawImageText");
        var json = JSON.parse(image);
        context.fillStyle = json.color;
        switch (json.shape) {
        case "circle":
            context.beginPath();
            context.arc(json.coords.x, json.coords.y, 5, 0, 2 * Math.PI, false);
            context.fill();
            break;
        case "square":
        default:
            context.fillRect(json.coords.x, json.coords.y, 10, 10);
            break;
        }
    }

    傳送的 JSON 結構將類似於以下內容:

    {
     "shape": "square",
     "color": "#FF0000",
     "coords": {
     "x": 31.59999942779541,
     "y": 49.91999053955078
     }
    } 

    現在,您需要新增 sendText(json) 方法以使用 websocket.send() 傳送 JSON 字串。

  5. 在編輯器中開啟 websocket.js,然後新增以下方法,用於將 JSON 傳送到端點,以及在從端點收到訊息時繪製圖像。
    websocket.onmessage = function(evt) { onMessage(evt) };
    
    function sendText(json) {
        console.log("sending text: " + json);
        websocket.send(json);
    }
                    
    function onMessage(evt) {
        console.log("received: " + evt.data);
        drawImageText(evt.data);
    }

    注:可以刪除已新增到 websocket.js 中的程式碼以測試端點。

  6. 將以下行(粗體)新增到 index.html 的底部以載入 whiteboard.js
            </table>
        <script type="text/javascript" src="websocket.js"></script>
        <script type="text/javascript" src="whiteboard.js"></script>
    <body>
                    

實現編碼器和解碼器介面

在此練習中,將建立用於實現解碼器和編碼器介面的類,以便將 Web 套接字訊息 (JSON) 解碼為 POJO 類 Figure,並將 Figure 編碼為 JSON 字串以傳送到端點。

  1. 右鍵單擊專案節點,然後選擇 "New"(新建)> "Java Class"(Java 類)。
  2. 鍵入 FigureEncoder 作為類名,並在 "Package"(包)下拉列表中選擇 org.sample.whiteboardapp。單擊 "Finish"(完成)。
  3. 在原始碼編輯器中,通過新增以下程式碼(粗體)來實現 WebSocket 編碼器介面:
                
    public class FigureEncoder implements Encoder.Text<Figure> {
        
    }
  4. 為 javax.websocket.Encoder 新增 import 語句並實現抽象方法。

    將游標放在類宣告中,按下 Alt-Enter 組合鍵,然後從彈出選單中選擇 Implement all abstract methods(實現所有抽象方法)。

  5. 通過進行以下更改(粗體)修改生成的抽象方法。儲存所做的更改。
        @Override
        public String encode(Figure figure) throws EncodeException {
            return figure.getJson().toString();
        }
    
        @Override
        public void init(EndpointConfig ec) {
            System.out.println("init");
        }
    
        @Override
        public void destroy() {
            System.out.println("destroy");
        }
  6. 右鍵單擊專案節點,然後選擇 "New"(新建)> "Java Class"(Java 類)。
  7. 鍵入 FigureDecoder 作為類名,並在 "Package"(包)下拉列表中選擇 org.sample.whiteboardapp。單擊 "Finish"(完成)。
  8. 在原始碼編輯器中,通過新增以下程式碼(粗體)來實現 WebSocket 解碼器介面:
                
    public class FigureDecoder implements Decoder.Text<Figure> {
        
    }
  9. 為 javax.websocket.Decoder 新增 import 語句並實現抽象方法。
  10. 對生成的抽象方法進行以下更改(粗體)。
        @Override
        public Figure decode(String string) throws DecodeException {
            JsonObject jsonObject = Json.createReader(new StringReader(string)).readObject();
            return  new Figure(jsonObject);
        }
    
        @Override
        public boolean willDecode(String string) {
            try {
                Json.createReader(new StringReader(string)).readObject();
                return true;
            } catch (JsonException ex) {
                ex.printStackTrace();
                return false;
            }
        
        }
    
        @Override
        public void init(EndpointConfig ec) {
            System.out.println("init");
        }
    
        @Override
        public void destroy() {
            System.out.println("destroy");
        }
  11. 修復匯入並儲存更改。

現在,您需要修改 MyWhiteboard.java 以指定編碼器和解碼器。

執行應用程式

您現在幾乎準備好執行應用程式了。在此練習中,您將修改 WebSocket 端點類以便為 JSON 字串指定編碼器和解碼器,並新增方法以便在收到訊息時將 JSON 字串傳送到已連線的客戶端。

  1. 在編輯器中開啟 MyWhiteboard.java
  2. 修改 @ServerEndpoint 標註以便為端點指定編碼器和解碼器。請注意,您需要顯式為端點的名稱指定 value 引數。
    @ServerEndpoint(value="/whiteboardendpoint", encoders = {FigureEncoder.class}, decoders = {FigureDecoder.class})
            
  3. 刪除預設情況下生成的 onMessage 方法。
  4. 新增以下 broadcastFigure 方法並使用 @OnMessage 標註該方法。
        @OnMessage
        public void broadcastFigure(Figure figure, Session session) throws IOException, EncodeException {
            System.out.println("broadcastFigure: " + figure);
            for (Session peer : peers) {
                if (!peer.equals(session)) {
                    peer.getBasicRemote().sendObject(figure);
                }
            }
        }
  5. 在編輯器中右鍵單擊,然後選擇 "Fix Imports"(修復匯入)(Alt-Shift-I 組合鍵;在 Mac 上為 ⌘-Shift-I 組合鍵)。儲存所做的更改。
  6. 在 "Projects"(專案)視窗中右鍵單擊專案,然後選擇 "Run"(執行)。

注:您可能需要從應用程式伺服器取消部署以前的應用程式,或者強制在瀏覽器中重新載入此頁。

如果檢視瀏覽器訊息,您會看到每次在畫布中單擊時,都會通過 JSON 將字串傳送到端點。

瀏覽器中應用程式的螢幕快照

如果將另一個瀏覽器開啟到 http://localhost:8080/WhiteboardApp/,您會看到每次在一個瀏覽器的畫布中單擊時,都會在另一個瀏覽器的畫布中重新生成新的圓形或方形。

兩個瀏覽器中應用程式的螢幕快照

向端點發送二進位制資料

應用程式現在可以處理字串並通過 JSON 將字串傳送到端點,然後將字串傳送到已連線的客戶端。在此部分,您將修改 JavaScript 檔案以傳送和接收二進位制資料。

要將二進位制資料傳送到端點,您需要將 WebSocket 的 binaryType 屬性設定為 arraybuffer。這可確保通過 ArrayBuffer 完成使用 WebSocket 的任何二進位制資料傳輸。由 whiteboard.js 中的 defineImageBinary 方法執行二進位制資料轉換。

  1. 開啟 websocket.js,然後新增以下程式碼以將 WebSocket 的 binaryType 屬性設定為 arraybuffer
    websocket.binaryType = "arraybuffer";
  2. 新增以下方法以將二進位制資料傳送到端點。
    function sendBinary(bytes) {
        console.log("sending binary: " + Object.prototype.toString.call(bytes));
        websocket.send(bytes);
    }
  3. 修改 onMessage 方法以新增以下程式碼(粗體),從而選擇該方法用於根據傳入訊息中的資料型別更新畫布。
    function onMessage(evt) {
        console.log("received: " + evt.data);
        if (typeof evt.data == "string") {
            drawImageText(evt.data);
        } else {
            drawImageBinary(evt.data);
        }
    }

    如果收到包含二進位制資料的訊息,則會呼叫 drawImageBinary 方法。

  4. 開啟 whiteboard.js 並新增以下方法。在解析傳入的二進位制資料之後,會呼叫 drawImageBinary 方法以更新畫布。defineImageBinary 方法用於將畫布快照準備為二進位制資料。
    function drawImageBinary(blob) {
        var bytes = new Uint8Array(blob);
    //    console.log('drawImageBinary (bytes.length): ' + bytes.length);
        
        var imageData = context.createImageData(canvas.width, canvas.height);
        
        for (var i=8; i<imageData.data.length; i++) {
            imageData.data[i] = bytes[i];
        }
        context.putImageData(imageData, 0, 0);
        
        var img = document.createElement('img');
        img.height = canvas.height;
        img.width = canvas.width;
        img.src = canvas.toDataURL();
    }
                        
    function defineImageBinary() {
        var image = context.getImageData(0, 0, canvas.width, canvas.height);
        var buffer = new ArrayBuffer(image.data.length);
        var bytes = new Uint8Array(buffer);
        for (var i=0; i<bytes.length; i++) {
            bytes[i] = image.data[i];
        }
        sendBinary(buffer);
    }

    現在,當您想要以 ArrayBuffer 型別生成二進位制資料並將其傳送到端點時,需要新增一種方法來呼叫 defineImageBinary

  5. 開啟 index.html,然後修改 <table> 元素以將以下行新增到窗體中的表中。
    <tr>
        <th> </th>
        <td><input type="submit" value="Send Snapshot" onclick="defineImageBinary(); return false;"></td>
        <td> </td>
        <td> </td>
        <td> </td>
    </tr>
                    

    新行包含 "Send Snapshot"(傳送快照)按鈕,用於將畫布的二進位制快照發送到已連線的對等方。單擊此按鈕時,將呼叫 whiteboard.js 中的defineImageBinary 方法。

  6. 開啟 MyWhiteboard.java,然後新增以下方法,用於在端點收到包含二進位制資料的訊息時將二進位制資料傳送到對等方。
    @OnMessage
    public void broadcastSnapshot(ByteBuffer data, Session session) throws IOException {
        System.out.println("broadcastBinary: " + data);
        for (Session peer : peers) {
            if (!peer.equals(session)) {
                peer.getBasicRemote().sendBinary(data);
            }
        }
    }

    注:需要為 java.nio.ByteBuffer 新增 import 語句。

可以修改應用程式以使使用者能夠停止向端點發送資料。預設情況下,只要對等方打開了頁面就會立即連線所有這些對等方,並將資料從瀏覽器傳送到連線的所有對等方。可以新增簡單條件,以便只有在選擇了此選項時才會將資料傳送到端點。這並不影響接收資料。仍會從端點接收資料。

  1. 修改 whiteboard.js 中的 defineImage 方法以新增以下程式碼(粗體)。
            drawImageText(json);
        if (document.getElementById("instant").checked) {
            sendText(json);
        }
    }

    檢查元素的 ID 是否為 checked 的條件程式碼

  2. 開啟 index.html,然後修改 <table> 元素以向窗體中新增複選框。
    <tr>
        <th> </th>
        <td><input type="submit" value="Send Snapshot" onclick="defineImageBinary(); return false;"></td>
        <td><input type="checkbox" id="instant" value="Online" checked="true">Online</td>
        <td> </td>
        <td> </td>
    </tr>
                    

    取消選中 "Online"(聯機)複選框時不會發送資料,但客戶端仍將從端點接收資料。

如果新增 "Send Snapshot"(傳送快照)按鈕和 "Online"(聯機)複選框並再次執行應用程式,則您將會在索引頁中看到新元素。如果開啟另一個瀏覽器並取消選中 "Online"(聯機)按鈕,您會看到在畫布中單擊時不會將 JSON 訊息傳送到端點。

瀏覽器中應用程式的螢幕快照

如果單擊 "Send Snapshot"(傳送快照),則二進位制資料將傳送到端點並廣播到已連線的客戶端。

轉載網址:https://netbeans.org/kb/docs/javaee/maven-websocketapi_zh_CN.html