Создать рукопожатие с помощью веб-сокета, используя Android в качестве сервера и браузер в качестве клиента

Я хотел бы иметь возможность использовать браузер в качестве редактора для смс на моем устройстве 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

2 ответа

Решение

Я наконец мог сделать рукопожатие 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 "";
}

Ну, этот код не совсем правильно.

Википедия очень хорошо объясняет, как работает рукопожатие WebSocket и как Sec-WebSocket-Accept рассчитывается: http://en.wikipedia.org/wiki/WebSocket

Другие вопросы по тегам