介绍
HTML5规范了web浏览器的能力建立全双工TCP连接与websocket服务器兼容。
换句话说,浏览器现在可以与服务器建立连接,通过相同的发送或接收数据建立通信通道,无需由HTTP协议本身引入的开销。
在本教程中,我们将实现一个简单的Java EE环境中websocket服务器端点以及相应的客户端发送和接收数据的基础设施。
本教程将下列环境:
- Ubuntu 12.04
- JDK 1.7.0.21
- Glassfish 4.0
WebSocket服务器端点
让我们定义一个Java EE websocket服务器端点:
package com.byteslounge.websockets; import java.io.IOException; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/websocket") public class WebSocketTest { @OnMessage public void onMessage(String message, Session session) throws IOException, InterruptedException { // Print the client message for testing purposes System.out.println("Received: " + message); // Send the first message to the client session.getBasicRemote().sendText("This is the first server message"); // Send 3 messages to the client every 5 seconds int sentMessages = 0; while(sentMessages < 3){ Thread.sleep(5000); session.getBasicRemote(). sendText("This is an intermediate server message. Count: " + sentMessages); sentMessages++; } // Send a final message to the client session.getBasicRemote().sendText("This is the last server message"); } @OnOpen public void onOpen() { System.out.println("Client connected"); } @OnClose public void onClose() { System.out.println("Connection closed"); } }
正如你可能已经注意到我们进口的几类 javax.websocket 包中。
@ServerEndpoint 注释用于类型水平和当前类定义为一个websocket服务器端点。 这个注释中使用的值代表端点的URL将监听客户端连接。
onOpen 和 onClose 方法注释与 @OnOpen 和 @OnClose 分别。 这些注释几乎是不言而喻的:他们定义哪些方法将呼吁一个新的客户端连接和断开。
方法 onMessage 有注释的 @OnMessage 。 这个注释定义的方法将调用当收到新消息从客户端。 注意,这个方法可以定义一个可选参数的类型 javax.websocket.Session (在我们的例子中 会话 参数)。 如果这个参数是定义了容器将注入会话相关联与当前客户端发送的消息被处理。
在我们的例子中我们只是客户端消息内容写入到标准输出。 然后我们继续发送消息到客户端之后,用5秒间隔3测试消息。 最后我们最后一个消息发送到客户端。
客户端
现在我们需要写我们websocket测试应用程序的客户端:
<!DOCTYPE html>
<html>
<head> <title>Testing websockets</title> </head> <body> <div> <input type="submit" value="Start" onclick="start()" /> </div> <div id="messages"></div> <script type="text/javascript"> var webSocket = new WebSocket('ws://localhost:8080/byteslounge/websocket'); webSocket.onerror = function(event) { onError(event) }; webSocket.onopen = function(event) { onOpen(event) }; webSocket.onmessage = function(event) { onMessage(event) }; function onMessage(event) { document.getElementById('messages').innerHTML += '<br />' + event.data; } function onOpen(event) { document.getElementById('messages').innerHTML = 'Connection established'; } function onError(event) { alert(event.data); } function start() { webSocket.send('hello'); return false; } </script> </body> </html>
这是一个简单的测试页面,其中包含的JavaScript创建一个websocket连接了websocket服务器端点。
onOpen 方法将调用当我们与服务器建立连接端点。
onError 方法被调用时,当一个错误发生在客户端和服务器之间的通信。
onMessage 方法将调用从服务器收到消息时。 在我们的例子中我们只是附加DOM的从服务器接收到的消息。
我们连接到websocket服务器端点通过构造 新的WebSocket() 并通过端点URL:
ws:/ / localhost:8080 / byteslounge / websocket
测试
我们现在可以测试我们的应用程序通过访问测试页面:
http://localhost:8080 / byteslounge / page.html
我们将会看到的 连接建立 消息如预期:
现在当我们按下这个按钮将通过websocket服务器发送初始消息和接收后续测试由服务器发送的消息:
websocket握手
客户机和服务器之间的TCP连接建立后的发生在HTTP协议握手。 很容易观察握手通过HTTP流量调试器。 一旦我们创建的 WebSocket 实例在客户端请求和各自的服务器响应会发生如下:
请注意 :我们将只包括相关的HTTP头websockets握手
要求:
连接:升级
升级:websocket
Sec-WebSocket-Key:wVlUJ / tu9g6EBZEh51iDvQ = =
回应:
升级:websocket
Sec-WebSocket-Accept:2 tnh + 0 h5gtx019lci6mnvs66psy =
请注意,客户端请求协议升级到WebSocket协议通过使用 连接:升级 和 升级:websocket HTTP头信息。 服务器响应,客户端请求被接受,它将改变协议WebSocket(使用HTTP状态代码101):
HTTP / 1.1 101 Web Socket协议握手
下载样例
示例源代码可供下载的这个页面。 测试在Glassfish 4被处决(你需要一个Java EE 7兼容的应用程序服务器)。
从本文下载源代码