Websocket握手在Java中失败 [英] Websocket Handshake Failed In Java

查看:165
本文介绍了Websocket握手在Java中失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我正在尝试解析一个使用websocket向客户端发送数据的网站。据我所读:

So, I'm trying to parse a website which uses websocket to send data to clients. From what I've read:

  • Link 1
  • Link 2

我了解到,为了创建连接,我需要向服务器发送一个特殊的http请求,然后我将检索一些用于访问该频道的数据。

I understood that for creating a connection, I need to send a special http request to server and ot will retrieve some data which i use to access the channel.

我做了什么:


  • 创建了http请求

  • created the http request

`URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();

// optional default is GET
con.setRequestMethod("GET");

//add request header
con.setRequestProperty("Cache-Control", "no-cache");
con.setRequestProperty("Host", "www.example.com");
con.setRequestProperty("Upgrade", "websocket");
con.setRequestProperty("Connection", "upgrade");
con.setRequestProperty("Origin", "https://example.com");
con.setRequestProperty("Sec-WebSocket-Extensions", "x-webkit-deflate-frame");
con.setRequestProperty("Sec-WebSocket-Key", "QkWkChtTGpaZL5PkOMaRtg==");
con.setRequestProperty("Sec-WebSocket-Version", "13");
con.setRequestProperty("User-Agent", "Mozilla/..;

`

我读了代码200的响应(不应该是101)。

and i read the response with code 200(not 101 which is supposed to be).

问题:


  1. 如何生成Sec-Websocket-Key?(例如取自萤火虫,实际所有标题)

1.1。可以做些什么?

1.1. What can be done more?

1.2。来自http的相同链接必须用于访问websocket?只能使用wss而不是https?

1.2. The same link from http must be used to access the websocket? only with wss instead of https?


  • 我尝试将客户端连接到服务器并在onMessage方法中接收消息。

  • after this I try to connect the client to server and receive messages in onMessage method.

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
会话会话= container.connectToServer(ClientEndpoint.class,buildCEC(),新URI(wss://async.example.com/socket.io/1/?t =+ System.currentTimeMillis()));

我尝试在buildCec()中插入标题以连接到服务器。

ClientEndpointConfig config = ClientEndpointConfig.Builder.create()。build();
Configurator conf = config.getConfigurator();

I tried in buildCec() to insert headers to connection to server. ClientEndpointConfig config = ClientEndpointConfig.Builder.create().build(); Configurator conf = config.getConfigurator();

`Map<String, List<String>> headers = new HashMap<String, List<String>>();

headers.put("Connection", Arrays.asList("keep-alive", "Upgrade"));
headers.put("Sec-Websocket-Extensions", Arrays.asList("x-webkit-deflate-frame"));
headers.put("Sec-Websocket-key", Arrays.asList("cx36sHrtuW9HZAaB6kKa/Q=="));
headers.put("Sec-Websocket-Version", Arrays.asList("13"));
headers.put("Upgrade", Arrays.asList("websocket"));
headers.put("User-Agent", Arrays.asList("Mozill..."));

conf.beforeRequest(headers);

return config;`


问题


  1. 我的判断是否良好,以防我解决并从http升级请求中收到101状态代码?(我的意思是,我接下来要做什么呢?)

  2. 请不要评判我,我刚开始使用java中的websockets,我不太了解javascript,我想要用jsr-356在纯java中做这个客户端。我已经用websockets做了一些小例子,但我找不到一个好的客户端,有标题和更复杂的握手。

  3. 是否可以连接到未知服务器,而不是了解所有细节?

我正在使用编程端点并导入javax.websocket.ContainerProvider;用于处理来自jsr356的websocket连接。

I'm using a programatic endpoint and import javax.websocket.ContainerProvider; for dealing the websocket connection from jsr356.

推荐答案

这里有很多主题。


  1. 不要对WebSocket使用URLHttpConnection,它根据HTTP语义管理输出/输入流,不处理升级连接。使用标准套接字。

  2. 阅读 RFC-6455:WebSocket协议

  3. 在RFC6455中多次提到 Sec-WebSocket-Key ,它有1个总体目的,供客户端使用证明它从服务器收到了有效的 WebSocket打开握手。客户端有规则,服务器端有关于它应该做什么的规则,以及它应该如何响应它。 (简而言之,它是客户端选择的随机值,发送到服务器,服务器在RFC指定的GUID上执行此步骤,计算SHA-1哈希值,并在其自己的中使用此哈希值进行响应Sec-WebSocket-Key ,客户端验证确认服务器确实支持WebSocket)

  4. 阅读Section 5.2。基本成帧协议,特别是围绕3种有效载荷长度的部分(你必须实现对所有3的支持,因为服务器需要规则来验证这一点)' - 参见其他回答这个问题 - 长篇Java Websocket文本框错误> ; = 128?

  5. 至于 javax.websocket.server.ServerEndpointConfig.Configurator ,您无法调用这些方法。这些是在建立连接的过程中由JSR-356 websocket服务器实现调用的。请参阅我关于此过程的其他答案 - 访问HttpSession来自Web Socket @ServerEndpoint中的HttpServletRequest

  6. 请注意框架验证规则 - 如何用Java解析和验证WebSocket框架?

  1. Don't use URLHttpConnection for WebSocket, it manages the output/input streams based on HTTP semantics, with no handling for Upgraded Connections. Use standard Socket.
  2. Read RFC-6455: The WebSocket Protocol
  3. The Sec-WebSocket-Key is mentioned many times in RFC6455, it has 1 overall purpose, for the client to prove that it received a valid WebSocket opening handshake from the server. There's rules for the client side, and rules for the server side on what it should do with it, and how it should respond to it. (in short, its a random value that the client picks, sends to the server, the server tacks on RFC specified GUID for this step, calculates an SHA-1 hash, and responds with this hash in its own Sec-WebSocket-Key, which the client validates to confirm that the server is really WebSocket capable)
  4. Read Section 5.2. Base Framing Protocol carefully, especially the parts around the 3 forms of payload length (you MUST implement support for all 3, as there are required rules for servers to validate this)' - see other answer about this - Java Websocket Text Frame Error at length >=128?
  5. As for javax.websocket.server.ServerEndpointConfig.Configurator, those methods cannot be called by you. Those are called by the JSR-356 websocket server implementation in the process of establishing a connection. See my other answer about this process - Accessing HttpSession from HttpServletRequest in a Web Socket @ServerEndpoint
  6. Be aware of the frame validation rules - How to parse and validate a WebSocket frame in Java?

我知道有几个JSR-356独立客户端。

There are a few JSR-356 standalone clients I'm aware of.

  • Eclipse Jetty 9.1+
    <dependency>
      <groupId>org.eclipse.jetty.websocket</groupId>
      <artifactId>javax-websocket-client-impl</artifactId>
      <version>9.1.0.v20131115</version>
    </dependency>




  • Apache Tomcat 8.0+

    • Apache Tomcat 8.0+
    •     <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-websocket</artifactId>
            <version>8.0.0-RC5</version>
          </dependency>
          <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-coyote</artifactId>
            <version>8.0.0-RC5</version>
          </dependency>
      




      • Project Grizzly

        • Project Grizzly
        •     <dependency>
                <groupId>org.glassfish.grizzly</groupId>
                <artifactId>grizzly-websockets</artifactId>
                <version>2.3.8</version>
              </dependency>
          




          • Glassfish Tyrus

            • Glassfish Tyrus
            •     <dependency>
                    <groupId>org.glassfish.tyrus.bundles</groupId>
                    <artifactId>tyrus-standalone-client</artifactId>
                    <version>1.3.3</version>
                  </dependency>
              

              如果你自己编写自己的WebSocket客户端,请务必根据 Autobahn WebSocket Protocol Testsuite (每个人都会针对这个测试套件编写实现测试,它有点成为事实上的协议验证套件)

              If you do write your own WebSocket client, be sure you test it against the Autobahn WebSocket Protocol Testsuite (everyone who write an implementation tests against this testsuite, its kinda become the de facto protocol validation suite)

              这篇关于Websocket握手在Java中失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆