Java – WebSocket 发送十六进制 0x0A

huangapple go评论91阅读模式
英文:

Java - WebSocket sending Hex 0x0A

问题

我一直在开发Android(Java)应用程序,以创建一个WebSocket服务器,一切都很顺利,连接也被接受。

问题出在向客户端(浏览器WebSocket)发送消息:

  1. OutputStream writer = client.getOutputStream();
  2. // FIN OPCODE 1000 0001
  3. writer.write(0x81);
  4. // 消息长度
  5. writer.write(0x5);
  6. writer.write('H');
  7. writer.write('e');
  8. writer.write('l');
  9. writer.write('l');
  10. writer.write('o');
  11. writer.flush();

我收到了一个错误:failed: Invalid frame header

我安装了Wireshark来查看问题:

Java – WebSocket 发送十六进制 0x0A

在右侧,您将看到数据

- 0x0A -> 问题所在。

  • 0x81 -> FIN & OPCODE (10000001)
  • 0x05 -> 消息长度
  • 0x48 0x65 0x6c 0x6c -> Hello

====== 更多代码 =======

我如何读取客户端请求(头部)?

  1. private String readClientInputStream() {
  2. String str = null;
  3. try {
  4. InputStream in = client.getInputStream();
  5. byte[] buffer = new byte[1024];
  6. int countBytesRead = in.read(buffer);
  7. if (countBytesRead > 0) {
  8. str = new String(buffer, 0, countBytesRead);
  9. }
  10. } catch (IOException e) {
  11. e.printStackTrace();
  12. }
  13. return str;
  14. }

使用str来获取Sec-WebSocket-Key并发送响应(握手):

  1. public void sendWebSocketHandShake(String str) {
  2. String[] result = str.split("Sec-WebSocket-Key: ", -1)[1].split("\\n");
  3. String key = makeKeyAccept(result[0]); // 下面的方法
  4. StringBuilder handshake_str = new StringBuilder();
  5. handshake_str.append("HTTP/1.1 101 Switching Protocols\n");
  6. handshake_str.append("Upgrade: websocket\n");
  7. handshake_str.append("Connection: Upgrade\n");
  8. handshake_str.append("Sec-WebSocket-Accept: ").append(key).append("\n");
  9. handshake_str.append("\n");
  10. try {
  11. OutputStream out = client.getOutputStream();
  12. byte[] b = handshake_str.toString().getBytes(StandardCharsets.UTF_8);
  13. out.write(b, 0, b.length);
  14. out.flush();
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. }

如何生成Sec-WebSocket-Accept密钥?

  1. public String makeKeyAccept(String key) {
  2. String _acceptKey = key.trim() + WEBSOCKET_KEY_MAGIC;
  3. MessageDigest digest = null;
  4. String base64 = null;
  5. try {
  6. digest = MessageDigest.getInstance("SHA-1");
  7. digest.update(_acceptKey.getBytes(StandardCharsets.UTF_8));
  8. byte[] encoded = android.util.Base64.encode(digest.digest(), 0, digest.getDigestLength(), android.util.Base64.DEFAULT);
  9. base64 = new String(encoded, 0, encoded.length, StandardCharsets.UTF_8);
  10. } catch (Exception ignore) {}
  11. return base64;
  12. }
英文:

I have been working on Android(Java) App, to create a websocket server,
all went good, and the connection is accepted.

The problem is sending a message to client (Browser webSocket)

  1. OutputStream writer = client.getOutputStream();
  2. // FIN OPCODE 1000 0001
  3. writer.write(0x81);
  4. // message length
  5. writer.write(0x5);
  6. writer.write('H');
  7. writer.write('e');
  8. writer.write('l');
  9. writer.write('l');
  10. writer.write('o');
  11. writer.flush();

I got an Error : failed: Invalid frame header

i installed webshark to see the problem:

Java – WebSocket 发送十六进制 0x0A

On the Right you will see the data

- 0x0A -> the problem.

  • 0x81 -> FIN & OPCODE (10000001)
  • 0x05 -> length of the message
  • 0x48 0x65 0x6c 0x6c -> Hell

====== MORE CODE =======

How i read the client request (headers) ?

  1. private String readClientInputStream() {
  2. String str = null;
  3. try {
  4. InputStream in = client.getInputStream();
  5. byte[] buffer = new byte[1024];
  6. int countBytesRead = in.read(buffer);
  7. if (countBytesRead > 0) {
  8. str = new String(buffer, 0, countBytesRead);
  9. }
  10. } catch (IOException e) {
  11. e.printStackTrace();
  12. }
  13. return str;
  14. }

Using str to get Sec-WebSocket-Key and sending response (handshake):

  1. public void sendWebSocketHandShake(String str) {
  2. String[] result = str.split("Sec-WebSocket-Key: ", -1)[1].split("\\n");
  3. String key = makeKeyAccept(result[0]); // METHOD CODE BELLOW
  4. StringBuilder handshake_str = new StringBuilder();
  5. handshake_str.append("HTTP/1.1 101 Switching Protocols\n");
  6. handshake_str.append("Upgrade: websocket\n");
  7. handshake_str.append("Connection: Upgrade\n");
  8. handshake_str.append("Sec-WebSocket-Accept: ").append(key).append("\n");
  9. handshake_str.append("\n");
  10. try {
  11. OutputStream out = client.getOutputStream();
  12. byte[] b = handshake_str.toString().getBytes(StandardCharsets.UTF_8);
  13. out.write(b, 0, b.length);
  14. out.flush();
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. }

How i make Sec-WebSocket-Accept key ?

  1. public String makeKeyAccept(String key) {
  2. String _acceptKey = key.trim() + WEBSOCKET_KEY_MAGIC;
  3. MessageDigest digest = null;
  4. String base64 = null;
  5. try {
  6. digest = MessageDigest.getInstance("SHA-1");
  7. digest.update(_acceptKey.getBytes(StandardCharsets.UTF_8));
  8. byte[] encoded = android.util.Base64.encode(digest.digest(), 0, digest.getDigestLength(), android.util.Base64.DEFAULT);
  9. base64 = new String(encoded, 0, encoded.length, StandardCharsets.UTF_8);
  10. } catch (Exception ignore){}
  11. return base64;
  12. }

答案1

得分: 0

谢谢 @MarkRotteveel

他告诉我问题可能来自于握手和残留字节...

在创建密钥base64后,我通过使用trim()来修复它。

英文:

Thank you @MarkRotteveel

As he told me the problem could be from the handshake and left over byte..

i fixed it by using trim() after creating the key base64

huangapple
  • 本文由 发表于 2023年2月23日 22:13:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545979.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定