JavaWeb(3):WebSocket简介
参考书籍:《Pro Java for Web Apps》
WebSocket
用于解决浏览器和服务器的通信问题。在现有体系中,如果只是简单的使用Ajax
进行通信的话,容易出现的问题是只有浏览器发送请求时才能得到响应。也即当有新数据时,浏览器不能得知新数据的存在,也就不能及时发送请求获取新数据。
WebSocket
使用了HTTP/1.1 升级
特性。该特性的使用很简单,只需要在请求中包含头名称和值 $Connection: Upgrade$ ,并在额外的 $Upgrade$ 头中指定一个或多个协议的列表。如果服务器接收升级请求,那么将返回 $101\ \ Switching\ \ Protocols$ 。HTTP升级
提供的最重要的特性是我们可以使用任意协议,并且在升级完成后就不再使用HTTP
连接,我们可以用一个Socket
来代替,由此产生了WebSocket
协议。WebSocket
协议将使用心跳消息(分别称为 $ping$ 和 $pong$ )保持连接活跃,即周期性地发送小数据包。在连接升级为WebScoket
协议之后,文本和二进制消息可以持续在两个方向上发送且不需要关闭和重连了;而且HTTP
规范要求对应同一个主机名,只允许有两个并发连接,但由于我们升级为WebScoket
连接了,因此该规范也不存在了。
使用WebSocket
协议之前需先以HTTP
协议向服务器发送特殊请求,访问一个特殊的URL
,该URL
以ws
或者wss
开头,分别对应http
和https
,并且除了 $Connection: Upgrade$ 头之外,还包含一个 $Connection: websocket$ 头,用于指定服务器将连接升级为 WebSocket
协议。
HTML5(JavaScript)客户端API
WebSocket
并不是只能用于浏览器和服务器的通信中,理论上可以将其应用于任何支持其的应用程序中。但如果要编写使用WebSocket
进行连接的浏览器客户端终端,我们就要用到JavaScript
,尽管我们使用JavaScript
编写,但实际上WebSocket
是HTML5
的一部分。使用JavaScript
创建WebSocket
对象十分简单:
var connection = new WebSocket('ws://www.example.com/chat', {'chat.v1', 'chat.v2'});
WebSocket
构造函数第一个参数为连接所使用的URL
,第二个参数可选,为连接所使用的一个或多个协议,这些协议都是自己创建的,不受WebSocket
管理。
WebSocket
接口中包含 $readyState$ 属性表示当前状态,值为 $CONNECTING$, $OPEN$, $CLOSING$, $CLOSED$ 中的一个,包含四个事件:$onopen$, $onclose$, $onerror$, $onmessage$ ,前两者分别在 $readyState$ 由 $CLOSING$ 变为 $CLOSED$ 时和 $readyState$ 由 $CONNECTING$ 变为 $OPEN$ 时触发。传入 $onclose$ 方法的事件包含三个属性:$wasClean$, $code$, $reason$ ,传入 $onopen$ 的是普通的事件,传入 $onerror$ 和 $onmessage$ 的事件包含一个 $data$ 属性,在前者中是错误对象,而在后者则根据消息类型转变:消息为字符串,则 $data$ 也为字符串;消息为二进制数据,并且 $WebSocket.binaryType$ 将被默认设置为 $blob$ 时,$data$ 为 $Blob$ ,而 $WebSocket.binaryType$ 为 $arraybuffer$ 时,$data$ 为 $ArrayBuffer$ 。通常我们应该在实例化之后立即设置 $bianryType$ 的值。WebSocket
对象的 $send$ 方法接收 $string$, $Blob$, $ArrayBuffer$, $ArrayBufferView$ 中一个类型的参数,表示要传输的数据;并且在该方法的作用域内我们还可以使用 $WebSocket.bufferedAmount$ 属性,该属性的值为之前的 $send$ 调用还有多少需要传输到服务器的数据。WebSocket
的 $close$ 用于关闭连接,接收两个可选参数,第一个为关闭代码(默认为 $1000$ ),第二个为字符串,表示原因。
Java WebSocket API
Java WebSocket API
包含在Java EE 7
中,包含了客户端和服务端的API
,存储在包 $javax.websocket$ 中,可以在 Java EE
文档 中查询。
客户端API
方法 | 作用 |
---|---|
$WebSocketContainer.connectToServer$ | 连接远程终端和初始化握手,返回一个 $Session$ |
$ContainerProvider.getWebSocketContainer(\ )$ | 获取底层WebSocket 客户端的实现 |
通过 $@ClientEndpoint$ 注解,我们可以标注出客户端终端,在客户端终端中也有四个事件,分别使用 $@OnOpen$, $@OnClose$, $@OnError$, $@OnMessage$ 标注,可以在相关文档中查阅其参数。
服务端API
服务端终端可以使用 $@ServerEndpoint$ 注解标注,该注解需提供 $value$ 特性的值,用于表示该终端所在的相对URL
,以 $/$ 开头,允许模板参数,Web容器
将在每次收到WebSocket
连接时创建该类的实例,连接关闭后销毁。在服务端终端中同样包含四个使用 $@OnOpen$, $@OnClose$, $@OnError$, $@OnMessage$ 标注出的事件,并且在这些事件中我们还可以使用 $@PathParam$ 注解使用我们的模板参数。