【问题标题】:websocket protocol error when server deflates payload服务器放气有效负载时的websocket协议错误
【发布时间】:2017-04-06 12:13:04
【问题描述】:

我正在编写一个 Java websocket 服务器,它现在从客户端接收打开握手消息(在 Chrome 版本 57.0.2987.133(64 位)中)并响应完成握手,如下所示。

收到:GET / HTTP/1.1
收到:主机:本地主机:6789
收到:连接:升级
收到:编译指示:无缓存
收到:缓存控制:无缓存
收到:升级:websocket
收件:来源:http://localhost:8080
收到:Sec-WebSocket-版本:13
收到:用户代理:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
收到:接受编码:gzip、deflate、sdch、br
收到:接受-语言:en-US,en;q=0.8
收到:Sec-WebSocket-Key:L1IiUSGijbGmTpthWsebOg==
收到:Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits

发送:HTTP/1.1 101 交换协议
发送:升级:websocket
发送:连接:升级
发送:Sec-WebSocket-Accept:L5HXnDJGDMYbWr5gRcQMOwKNf3Q=
发送:接受编码:gzip、deflate
发送:Sec-WebSocket-Extensions:permessage-deflate; client_no_context_takeover; server_no_context_takeover

现在,客户端可以发送消息并且它没有问题地发送消息并且我的代码使用 java.util.zip.Deflater 成功解压缩它们并且......如果我的服务器以标题字节 0x81 响应(fin,无压缩,文本) 和 0x5 然后是 'hello' 的字节(例如)然后 Chrome 上的 javascript 中的 websocket 客户端完全满意,但是当我尝试压缩响应时,客户端总是关闭连接并引用错误代码 1002 和文本'Websocket协议错误”。

放气

    public void sendMessageDeflated(String rxMessage, OutputStream streamOut) {

    System.out.println("Message back to client is: " + rxMessage);

    // And then compress the response and send it out.
    Deflater compressor = new Deflater(Deflater.DEFLATED);
    try {
        int headerLength = 2;
        byte unzippedMsg[] = rxMessage.getBytes("UTF-8");
        compressor.setInput(unzippedMsg);
        compressor.finish();
        byte zippedMsg[] = new byte[2048];  // Nasty constant but will have to do for now.
        int toCompressLength = unzippedMsg.length;
        int compLength = compressor.deflate(zippedMsg, headerLength, zippedMsg.length - headerLength);
        compressor.end();

        zippedMsg[0] = (byte)0xC1; // FIN bit, compression plus opcode for TEXT MESSAGE
        zippedMsg[1] = (byte)((byte)0x00 | (byte)compLength); // No mask on return data.

        streamOut.write(zippedMsg, 0, compLength + headerLength);

    } catch ( IOException ioEx ) {
        // TBD
        System.out.println("IOException: " + ioEx.toString());
    } catch ( Exception ex ) {
        // TBD
        System.out.println("IOException: " + ex.toString());
    }
}

GZIP

    public void sendMessageGZipped(String rxMessage, OutputStream streamOut) {
    // Do something with the message here...

    System.out.println("Message back to client is: " + rxMessage);

    // And then compress the response and send it out.
    try {
        int headerLength = 2;
        byte unzippedMsg[] = rxMessage.getBytes("UTF-8");
        int toCompressLength = unzippedMsg.length;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream gzipOut = new GZIPOutputStream(baos);
        gzipOut.write(unzippedMsg, 0, toCompressLength);
        gzipOut.close();
        byte[] payload = baos.toByteArray();

        byte header[] = new byte[32];
        header[0] = (byte)0xC1; // FIN bit plus opcode for TEXT MESSAGE
        header[1] = (byte)((byte)0x00 | (byte)payload.length); // No mask on return data.

        streamOut.write(header, 0, 2);
        streamOut.write(payload);

    } catch ( IOException ioEx ) {
        // TBD
        System.out.println("IOException: " + ioEx.toString());
    } catch ( Exception ex ) {
        // TBD
        System.out.println("IOException: " + ex.toString());
    }
}

我尝试切换到二进制操作码,认为可能压缩文本 = 二进制,但这不起作用。我真的看不出我做错了什么或错过了什么。此实现不包括跨越消息的滑动压缩窗口。我认为响应标题清楚地表明了这一点。欣然接受帮助。

【问题讨论】:

    标签: java sockets websocket compression deflate


    【解决方案1】:

    我最终解决了这个问题,方法是构建客户端 websocket 代码并看到当它试图膨胀消息时抛出的异常:“无效的存储块长度”。这让我看到了这篇文章:Java decompressing array of bytes,其中谈到 Deflate 能够使用 zlib 包装器或不使用 zlib 包装器进行压缩。所以将上面的示例代码中的 processMessage2 中的一行更改为这个...

            Deflater compressor = new Deflater(Deflater.DEFLATED, true);
    

    ...将 'nowrap' 设置为 true。

    Chrome 浏览器客户端在其标头中声称支持 gzip。如果我得到这个工作,我会回到这里并发布答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多