【发布时间】: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