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