我正在尝试编写自己的WebSocket服务器。
我知道有一些框架,但我想学习,所以我自己做:)
我的JavaScript客户端当前使用onOpen
进行响应,因此我认为握手是有效的,并且建立了连接。
现在的问题是:
我的Java服务器使用一个选择器线程在Channel上进行读取。
如果我在客户端的WebSocket对象上执行*.send("test message")
,则服务器无法解码字节数组。
我没有发现关于所使用的编码/解码技术的信息,所以我尝试了许多版本来解码。
例如:
new String(Base64.decodeBase64(buffer.array()))
或
Charset set = Charset.forName("UTF-8");
new String(Base64.decodeBase64(set.decode(buffer).toString()))
消息完全从Channel读取到ByteBuffer中,所以我认为这不是问题所在。
有人能帮我吗?
好的,这篇文章可以帮助我向客户端发送数据。这很好:)
但我不知道如何解码从客户那里收到的数据:(
在客户处,我只发送一封信
socket.send("x");
服务器接收7字节???
ByteBuffer buffer = ByteBuffer.allocate(8192);
int read = client.getInputStream().read(buffer2.array());
System.out.println("read: " + read);
// read: 7
for (int i = 0; i < read; i++) {
int j = buffer.get(i) & 0xff;
System.out.println("i: " + i + " => " + j + "=>" + new BigInteger(j + "").toString(2));
}
//i: 0 => 129=>10000001
//i: 1 => 129=>10000001
//i: 2 => 195=>11000011
//i: 3 => 235=>11101011
//i: 4 => 4=>100
//i: 5 => 96=>1100000
//i: 6 => 187=>10111011
如果我做这个
secondByte AND 0111 1111
(i:1)的结果是"1",我认为这意味着只有一个字节的数据。那为什么读是7???
至于第二个问题,从客户端到服务器的数据总是被屏蔽,正如我在上面的链接中所解释的那样。掩码占用4个字节。
因此,实际数据的长度实际上是1。只有第二个字节的最后7个比特说明了长度,而第一个比特没有,所以只需丢弃那个比特就可以得到000 0001
,也就是1
。
在这种情况下,字节分类如下:
- 0、1是元字节
- 3、4、5、6是口罩
- 7是数据
要获得数据,请计算data XOR masks[data_index MOD 4]
,即本例中的187 XOR 195
,即120
——x
的字符代码。
private String decodeMessage(){
try {
byte[] data = new byte[1024];
int size = in.read(data);
if (size == -1) return null;
byte[] decoded = new byte[size-6];
byte[] key = new byte[]{ data[2], data[3], data[4], data[5] };
for (int i = 0; i < size-6; i++) {
decoded[i] = (byte) (data[i+6] ^ key[i & 0x3]);
}
return new String(decoded, "UTF-8");
}catch (IOException ex){
ex.printStackTrace();
}
return "ping";
}
这段代码可能很糟糕,但它对我有效