2017-04-06 96 views
0

我正在编写Java websocket服务器,现在它从客户端(在Chrome版本57.0.2987.133(64位))收到打开握手消息,并响应完成握手如下所示。服务器卸载有效负载时出现websocket协议错误

收稿:GET/HTTP/1.1
收到的:主机:本地主机:6789
收稿:连接:升级
收稿:附注:无缓存
收稿:缓存控制:无缓存
收到 :升级:网页套接字
收稿:产地:http://localhost:8080
收稿:仲丁基的WebSocket-版本:13
收到的:用户代理:Mozilla的/ 5.0(Macintosh上;英特尔的Mac OS X 10_9_5)为AppleWebKit /537.36(KHTML,例如Gecko)铬/ 57.0.2987.133 Safari浏览器/ 537.36
收稿:接受编码:gzip,DEFLATE,SDCH,BR
收稿:接受语言:EN-US,EN; Q = 0.8
收到:Sec-WebSocket-Key:L1IiUSGijbGmTpthWsebOg ==
Received:Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits

发送:HTTP/1.1 101交换协议
发送:升级:网页套接字
发送:连接:升级
发送:仲丁基的WebSocket - 接受:L5HXnDJGDMYbWr5gRcQMOwKNf3Q =
发送:接受编码:gzip, deflate
发送:Sec-WebSocket-Extensions:permessage-deflate; client_no_context_takeover; server_no_context_takeover

现在,如果我的服务器用头字节0×81(鳍响应客户端可以发送消息和它这样做没有问题,我的代码使用它们和java.util.zip.Deflater中成功解压... ,没有压缩,文本)和0x5然后为'hello'的字节(作为一个例子),然后在Chrome上的JavaScript websocket客户端是完全开心,但是当我尝试压缩响应时,客户端总是关闭连接引用错误代码1002和文本'Websocket协议错误'。

DEFLATE

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()); 
    } 
} 

我试图切换到操作码二进制思维,也许压缩文本=二进制,但没有奏效。我真的不知道我做错了什么或错过了什么。此实现不包括跨越消息的滑动压缩窗口。我认为响应标题清楚地表明了这一点。帮忙感激地接受。

回答

0

我最终通过构建客户端websocket代码并在尝试对消息进行膨胀时看到异常:“无效的存储块长度”来解决此问题。这导致我到这篇文章:Java decompressing array of bytes谈论Deflate可以使用zlib wrapper或不使用压缩。因此,将processMessage2中的一行从上面的示例代码更改为此...

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

...将“nowrap”设置为true。

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