英文:
Java - WebSocket sending Hex 0x0A
问题
我一直在开发Android(Java)应用程序,以创建一个WebSocket服务器,一切都很顺利,连接也被接受。
问题出在向客户端(浏览器WebSocket)发送消息:
OutputStream writer = client.getOutputStream();
// FIN OPCODE 1000 0001
writer.write(0x81);
// 消息长度
writer.write(0x5);
writer.write('H');
writer.write('e');
writer.write('l');
writer.write('l');
writer.write('o');
writer.flush();
我收到了一个错误:failed: Invalid frame header
我安装了Wireshark来查看问题:

在右侧,您将看到数据
- 0x0A -> 问题所在。
- 0x81 -> FIN & OPCODE (10000001)
 - 0x05 -> 消息长度
 - 0x48 0x65 0x6c 0x6c -> Hello
 
====== 更多代码 =======
我如何读取客户端请求(头部)?
private String readClientInputStream() {
    String str = null;
    try {
        InputStream in = client.getInputStream();
        byte[] buffer = new byte[1024];
        int countBytesRead = in.read(buffer);
        if (countBytesRead > 0) {
            str = new String(buffer, 0, countBytesRead);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return str;
}
使用str来获取Sec-WebSocket-Key并发送响应(握手):
public void sendWebSocketHandShake(String str) {
    String[] result = str.split("Sec-WebSocket-Key: ", -1)[1].split("\\n");
    String key = makeKeyAccept(result[0]); // 下面的方法
    StringBuilder handshake_str = new StringBuilder();
    handshake_str.append("HTTP/1.1 101 Switching Protocols\n");
    handshake_str.append("Upgrade: websocket\n");
    handshake_str.append("Connection: Upgrade\n");
    handshake_str.append("Sec-WebSocket-Accept: ").append(key).append("\n");
    handshake_str.append("\n");
    try {
        OutputStream out = client.getOutputStream();
        byte[] b = handshake_str.toString().getBytes(StandardCharsets.UTF_8);
        out.write(b, 0, b.length);
        out.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
如何生成Sec-WebSocket-Accept密钥?
public String makeKeyAccept(String key) {
    String _acceptKey = key.trim() + WEBSOCKET_KEY_MAGIC;
    MessageDigest digest = null;
    String base64 = null;
    try {
        digest = MessageDigest.getInstance("SHA-1");
        digest.update(_acceptKey.getBytes(StandardCharsets.UTF_8));
        byte[] encoded = android.util.Base64.encode(digest.digest(), 0, digest.getDigestLength(), android.util.Base64.DEFAULT);
        base64 = new String(encoded, 0, encoded.length, StandardCharsets.UTF_8);
    } catch (Exception ignore) {}
    return base64;
}
英文:
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)
    OutputStream writer = client.getOutputStream();
    // FIN OPCODE 1000 0001
    writer.write(0x81);
    // message length
    writer.write(0x5);
    writer.write('H');
    writer.write('e');
    writer.write('l');
    writer.write('l');
    writer.write('o');
    writer.flush();
I got an Error : failed: Invalid frame header
i installed webshark to see the problem:
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) ?
private String readClientInputStream() {
    String str = null;
    try {
        InputStream in = client.getInputStream();
        byte[] buffer = new byte[1024];
        int countBytesRead = in.read(buffer);
        if (countBytesRead > 0) {
            str = new String(buffer, 0, countBytesRead);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return str;
}
Using str to get Sec-WebSocket-Key and sending response (handshake):
public void sendWebSocketHandShake(String str) {
    String[] result = str.split("Sec-WebSocket-Key: ", -1)[1].split("\\n");
    String key = makeKeyAccept(result[0]); // METHOD CODE BELLOW
    StringBuilder handshake_str = new StringBuilder();
    handshake_str.append("HTTP/1.1 101 Switching Protocols\n");
    handshake_str.append("Upgrade: websocket\n");
    handshake_str.append("Connection: Upgrade\n");
    handshake_str.append("Sec-WebSocket-Accept: ").append(key).append("\n");
    handshake_str.append("\n");
    try {
        OutputStream out = client.getOutputStream();
        byte[] b = handshake_str.toString().getBytes(StandardCharsets.UTF_8);
        out.write(b, 0, b.length);
        out.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
How i make Sec-WebSocket-Accept key ?
   public String makeKeyAccept(String key) {
        String _acceptKey = key.trim() + WEBSOCKET_KEY_MAGIC;
        MessageDigest digest = null;
        String base64 = null;
        try {
            digest = MessageDigest.getInstance("SHA-1");
            digest.update(_acceptKey.getBytes(StandardCharsets.UTF_8));
            byte[] encoded = android.util.Base64.encode(digest.digest(), 0, digest.getDigestLength(), android.util.Base64.DEFAULT);
            base64 = new String(encoded, 0, encoded.length, StandardCharsets.UTF_8);
        } catch (Exception ignore){}
        return base64;
    }
答案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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论