簡體   English   中英

Websocket(Jetty):如何處理服務器端分塊的二進制數據

[英]Websocket(Jetty) : How to handle the binary data on server side which is coming in chunks

我需要設置一個可以接收客戶端發送的音頻數據的 websocket 服務器。 為此,我正在使用 Jetty。

我的處理程序代碼:

{
    @OnWebSocketClose
    public void onClose(int statusCode, String reason) {
    }

    @OnWebSocketError
    public void onError(Throwable t) {
    }

    @OnWebSocketConnect
    public void onConnect(Session session) {

    }

    @OnWebSocketMessage
    public void onMessage(String message) {
    }

    @OnWebSocketMessage
    public void onMessage(bytes [] b) {
    }

    @OnWebSocketMessage
    public void inputStream(InputStream is) {
    }
}

由於音頻文件非常大,客戶端將它們分塊發送。 現在對於每個塊,都會調用onMessage(bytes [] b) {}方法。

在服務器端,我需要添加這些塊並處理音頻。 我怎樣才能做到這一點?

另外onMessage(bytes [] b) {}onMessage(InputStream is) {}方法有什么區別?

根據onMessage javadoconMessage(byte[] b)onMessage(InputStream is)都將收到整個消息:

如果該方法正在處理二進制消息:

  • byte[] 或 ByteBuffer 接收整個消息
  • InputStream 以阻塞流的形式接收整個消息

因此,如果您使用這些方法之一,Jetty 將自動重新組合塊並將整個消息傳遞給您的方法(作為byte[]數組或InputStream )。

二進制消息的最大大小,可以這樣接收,用setMaxBinaryMessageSize設置

另請注意,您可能一次只能在 Handler 類中定義以下方法之一:

每個 websocket 端點對於每種原生 websocket 消息格式可能只有一種消息處理方法:文本、二進制和 pong。

如果你想處理數據,你應該使用下面的方法簽名:

@OnMessage
public void processUpload(byte[] b, boolean last, Session session) {
    // process partial data here, which check on last to see if these is more on the way
}

並手動緩沖您的數據(在內存或磁盤文件等中)

反過來,客戶端應該使用sendPartialBytes方法之一, 塊發送數據。


如果您觀察到的是為每個數據塊調用的“完整消息”方法(即onMessage(byte[] b ),由客戶端發送,則表明客戶端沒有利用協議功能來發送分塊消息,而是拆分輸入數據,然后將其部分作為獨立的WS 消息發送,有效地創建了自己的應用程序級協議,用於以塊的形式傳輸數據。

在這種情況下,您必須更新客戶端(如果這是一個選項),使其使用常規 WS 協議功能,或者實現客戶端正在使用的相同“應用程序級協議”。

下面是一個超級簡單的端點示例,它將緩沖輸入數據,直到 WS 套接字關閉(這意味着客戶端將在發送所有塊后關閉連接)。

@ServerEndpoint("/data")
public static class Handler {

    private ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    @OnMessage
    public void onMessage(byte[] message) throws IOException {
        buffer.write(message);
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        System.out.println(
            buffer.toByteArray().length
        );
    }

}

此實現還意味着使用默認的ServerEndpointConfig.Configurator ,因此每個連接只有一個 Endpoint 實例(如此處所述)。

更復雜的實現可能希望重用套接字來發送多個文件,並指定一種機制來表示每次傳輸的開始和結束(例如,使用特殊格式的消息),但這完全取決於您的客戶端是如何實現的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM