3

我希望能够在我的 android 设备上使用浏览器作为短信编辑器(类似于https://www.mysms.com)。所以我开始编写一个充当套接字服务器并使用浏览器作为客户端的 android 应用程序(例如http://www.websocket.org/echo.html)。我能够从该客户端访问我的应用程序并从中获取消息,但我现在遇到了 WebSocket 握手(Sec-WebSocket-Key 等)的问题。

编辑:

我按照本教程编写了我的 android 服务器:http ://android-er.blogspot.co.at/2014/02/android-sercerclient-example-server.html

当我试图从http://www.websocket.org/echo.html访问该服务器时,我收到了这个 js 错误:WebSocket 握手期间出错:状态行无效

编辑:

所以我为 Sec-WebSocket-Accept: 行添加了带有编码密钥的标头

// get the key from the input 
InputStream inputStream = hostThreadSocket.getInputStream();
            String line = "";
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(inputStream));
                while ((line = reader.readLine()) != null) {
                    if(line.contains("Sec-WebSocket-Key:")){ // stop then the line containing the key is found
                        break;
                    }
                }

            } catch (IOException e) {
            }
String key = line.replace("Sec-WebSocket-Key:", "");

并使用以下方法对结果进行编码:

static String encodeString(String input)  {

    MessageDigest digest = null;
    try {
        digest = MessageDigest.getInstance("SHA-1");
        byte[] inputBytes = input.getBytes();
        byte[] hashBytes = digest.digest(inputBytes);
        return  Base64.encodeToString(hashBytes, Base64.DEFAULT);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return "";
}

并传递如下标题:

 String key = line.replace("Sec-WebSocket-Key:", "");
            key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            key = encodeString(key).replace("\n", "");;

            String header = "HTTP/1.1 101 Switching Protocols\r\n" +
                    "Upgrade: websocket \r\n" +
                    "Connection: Upgrade \r\n" +
                    "Sec-WebSocket-Accept: " + key + "\r\n"+
                    "Sec-WebSocket-Protocol: chat\r\n\r\n" + msgReply;
            printStream.print(header);
            printStream.close();

响应头现在看起来像这样:

Connection:Upgrade\r\n 
Sec-WebSocket-Accept:/Qg4DR68UCCo9VKy4vbDgswCU8Y=\r\n
Upgrade:websocket\r\n

但我仍然收到错误:失败:WebSocket 握手期间出错:“Sec-WebSocket-Accept”标头值不正确

4

2 回答 2

3

我终于可以进行 websocket 握手了。我不知道究竟是什么变化让我成功了,但这是工作代码:

InputStream inputStream = hostThreadSocket.getInputStream();
            String line = "";
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(inputStream));
                while ((line = reader.readLine()) != null) {
                    if (line.contains("Sec-WebSocket-Key: ")) { // check if its the header-line containing the websocket key
                        break;
                    }
                }
            } catch (IOException e) {
                Log.e(TAG_TEST, e.getMessage(), e);
            }

            Matcher matcher = pattern.matcher(line); // with pattern "Sec-WebSocket-Key:[ ]*([^\r^\n]*)" to parse the key out of the line
            boolean matches = matcher.matches();
            String key = matcher.group(1);
            key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // adding the "magic string"
            key = encodeString(key);

            String header = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +                       
                    "Upgrade: websocket\r\n" +
                    "Connection: Upgrade\r\n" +
                    "Sec-WebSocket-Accept:" + key + "\r\n\r\n";
            printStream.print(header);

这就是我对密钥进行编码的方法

static String encodeString(String input) {
    MessageDigest digest = null;
    try {
        digest = MessageDigest.getInstance("SHA-1");
        byte[] inputBytes = input.getBytes();
        byte[] hashBytes = digest.digest(inputBytes);
        return Base64.encodeToString(hashBytes, Base64.NO_WRAP);
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG_TEST, e.getMessage(), e);
    }
    return "";
}
于 2014-12-08T10:43:55.947 回答
0

好吧,该代码不太正确。

维基百科很好地解释了 WebSocket 握手的工作原理以及如何Sec-WebSocket-Accept计算:http ://en.wikipedia.org/wiki/WebSocket#WebSocket_protocol_handshake

于 2014-12-07T13:02:08.617 回答