当前位置: 首页 > 知识库问答 >
问题:

使用android作为服务器和浏览器作为客户端创建websocket握手

赏成益
2023-03-14

我希望能够使用浏览器作为我的android设备上的短信编辑器(类似https://www.mysms.com)。所以我开始写一个android应用程序,作为套接字服务器,并使用浏览器作为客户端(如<-我能够从那个客户端到达我的应用程序,并从它获取消息,但我现在有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-Access'头值

共有2个答案

施俊远
2023-03-14

那个代码不太对。

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

秦才
2023-03-14

我终于可以和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 "";
}
 类似资料:
  • 我正在同时开发一个服务器和它的客户端,我正在Docker容器中设计它们。我正在使用Docker Comment将它们连接起来,它在生产中工作得很好,但是我不知道如何在开发工作流中使它工作,在开发工作流中,我为每一个都运行了一个shell。 我的<代码>docker compose devel。yml: 我可以做甚至,但我想要的是服务器和客户端都运行一个shell,这样我就可以在迭代开发时对两者进行

  • 问题内容: 我正在尝试在Java中的服务器和JavaScript客户端之间建立连接,但在客户端出现此错误: WebSocket与“ ws://127.0.0.1:4444 /”的连接失败:在收到握手响应之前,连接已关闭 由于可能从未调用该函数,因此它可能保持在OPENNING状态。该不会被调用。 有人可以让我知道这里出了什么问题吗? 服务器 服务器线程 游戏协议 客户 问题答案: 首先,您的两个代

  • NewTLSServer创建的服务器可以验证对显式从其创建的客户端的调用: 在行中。 但是,我有一个生产程序,我想将其设置为使用作为主机。我越来越 我称之为错误。 我如何设置与客户端进行身份验证,就像普通的HTTPS服务器一样?

  • websocket客户端(使用Autobahn/Python和Twisted)需要连接到websocket服务器:客户端需要向服务器提供其客户端证书,客户端需要检查服务器的证书。例如,这些证书是在Kubernetes minikube安装过程中创建的。特别地: 服务器证书(据我所知为X509格式) 客户端证书~/。minikube/客户。按键 我已经检查过,我可以成功地使用这些证书密钥使用发出库伯

  • 问题内容: 如果我想在我的RMI应用程序中启用“双向”通信(即,允许服务器调用客户端上的方法,以及允许客户端调用服务器上的方法),则是使客户端成为还有远程课程吗? 另外,如果我打算将客户端的实例作为方法参数传递给服务器,我是否认为不需要在rmiregistry中添加“客户端类”是正确的吗? 最后一个问题,我所有的类是否仍需要在同一位置编译?IE可以在两台完全独立的计算机上编译服务器和客户端,并期望

  • 在本节中,我们将构建一个完整的的 Netty客 户端和服务器。虽然你可能集中在写客户端是浏览器的基于 Web 的服务,接下来你将会获得更完整了解 Netty 的 API 是如何实现客户端和服务器的。 Figure 2.1.Echo client / server 图中显示了连接到服务器的多个并发的客户端。在理论上,客户端可以支持的连接数只受限于使用的 JDK 版本中的制约。 echo(回声)客户端