所以,我正在尝试解析一个使用websocket向客户端发送数据的网站.从我读过的内容:
链接1
链接2
我知道,为了创建连接,我需要向服务器发送一个特殊的http请求,然后我将检索一些用于访问该通道的数据.
我做了什么:
创建了http请求
`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)读取响应.
问题:
如何生成Sec-Websocket-Key?(例如从firebug中获取,实际上所有头文件)
1.1.还能做些什么?
1.2.来自http的相同链接必须用于访问websocket吗?只用wss而不是https?
在此之后,我尝试将客户端连接到服务器并在onMessage方法中接收消息.
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
Session session = container.connectToServer(ClientEndpoint.class, buildCEC(), new URI("wss://async.example.com/socket.io/1/?t=" + System.currentTimeMillis()));
我尝试在buildCec()中插入标题以连接到服务器.
ClientEndpointConfig config = ClientEndpointConfig.Builder.create().build();
Configurator conf = config.getConfigurator();
`Map> headers = new HashMap >(); 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;`
问题
我的判断是好的,以防我解决并从http升级请求中收到101状态代码?(我的意思是,我接下来要做的是什么细节?)
请不要评判我,我刚开始使用java中的websockets,我不太了解javascript,我想用jsr-356在纯java中做这个客户端.我用websockets做了一些小例子,但我找不到一个好的客户端,有标题和更复杂的握手.
是否可以连接到未知服务器,而不知道所有细节?
我正在使用一个程序设计端点并导入javax.websocket.ContainerProvider; 用于处理来自jsr356的websocket连接.
这里有很多主题.
不要将URLHttpConnection用于WebSocket,它基于HTTP语义管理输出/输入流,不处理升级连接.使用标准插座.
阅读RFC-6455:WebSocket协议
将Sec-WebSocket-Key
在RFC6455多次提及,它有1个总体目标,为客户证明它接收到一个有效的WebSocket开放握手从服务器.客户端有规则,服务器端有关它应该做什么的规则,以及它应该如何响应它.(简而言之,它是客户端选择的随机值,发送到服务器,服务器在RFC指定的GUID上执行此步骤,计算SHA-1哈希值,并使用此哈希值进行响应,Sec-WebSocket-Key
客户端验证为确认服务器真的支持WebSocket)
阅读第5.2节.仔细地考虑基本帧协议,特别是3种有效载荷长度的部分(你必须实现对所有3的支持,因为服务器需要规则来验证这一点)' - 请参阅其他答案 - Java Websocket Text Frame Error > = 128?
至于javax.websocket.server.ServerEndpointConfig.Configurator
那些方法不能被你调用.这些是在建立连接的过程中由JSR-356 websocket服务器实现调用的.请参阅我关于此过程的其他答案 - 在Web Socket @ServerEndpoint中从HttpServletRequest访问HttpSession
请注意框架验证规则 - 如何在Java中解析和验证WebSocket框架?
我知道有几个JSR-356独立客户端.
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+
<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>
灰熊计划
<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-websockets</artifactId>
<version>2.3.8</version>
</dependency>
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进行测试(每个人都针对此测试套件编写实现测试,它有点成为事实上的协议验证套件)