一、文章导读
服务器推送你还在使用轮询吗?本文将带你领略WebSocket的魅力,轻松实现服务器推送功能。本文将以下面两方面让你理解WebSocket并应用到具体的开发中
- WebSocket概述
- 使用WebSocket实现网页聊天室
二、WebSocket
1. WebSocket介绍
WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。
这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步 AJAX 请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
http协议:
websocket协议:
2. websocket协议
本协议有两部分:握手和数据传输。
握手是基于http协议的。
来自客户端的握手看起来像如下形式:
GET ws://localhost/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Version: 13
来自服务器的握手看起来像如下形式:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Extensions: permessage-deflate
字段说明:
头名称 |
说明 |
Connection:Upgrade |
标识该HTTP请求是一个协议升级请求 |
Upgrade: WebSocket |
协议升级为WebSocket协议 |
Sec-WebSocket-Version: 13 |
客户端支持WebSocket的版本 |
Sec-WebSocket-Key: |
客户端采用base64编码的24位随机字符序列,服务器接受客户端HTTP协议升级的证明。要求服务端响应一个对应加密的Sec-WebSocket-Accept头信息作为应答 |
Sec-WebSocket-Extensions |
协议扩展类型 |
3. 客户端(浏览器)实现
3.1 websocket对象
实现 WebSockets 的 Web 浏览器将通过 WebSocket 对象公开所有必需的客户端功能(主要指支持 Html5 的浏览器)。
以下 API 用于创建 WebSocket 对象:
var ws = new WebSocket(url);
参数url格式说明: ws://ip地址:端口号/资源名称
3.2 websocket事件
WebSocket 对象的相关事件
事件 |
事件处理程序 |
描述 |
open |
websocket对象.onopen |
连接建立时触发 |
message |
websocket对象.onmessage |
客户端接收服务端数据时触发 |
error |
websocket对象.onerror |
通信发生错误时触发 |
close |
websocket对象.onclose |
连接关闭时触发 |
3.3 WebSocket方法
WebSocket 对象的相关方法:
方法 |
描述 |
send() |
使用连接发送数据 |
4. 服务端实现
Tomcat的7.0.5 版本开始支持WebSocket,并且实现了Java WebSocket规范(JSR356)。
Java WebSocket应用由一系列的WebSocketEndpoint组成。Endpoint 是一个java对象,代表WebSocket链接的一端,对于服务端,我们可以视为处理具体WebSocket消息的接口, 就像Servlet之与http请求一样。
我们可以通过两种方式定义Endpoint:
- 第一种是编程式, 即继承类 javax.websocket.Endpoint并实现其方法。
- 第二种是注解式, 即定义一个POJO, 并添加 @ServerEndpoint相关注解。
Endpoint实例在WebSocket握手时创建,并在客户端与服务端链接过程中有效,最后在链接关闭时结束。在Endpoint接口中明确定义了与其生命周期相关的方法, 规范实现者确保生命周期的各个阶段调用实例的相关方法。生命周期方法如下:
方法 |
含义描述 |
注解 |
onClose |
当会话关闭时调用。 |
@OnClose |
onOpen |
当开启一个新的会话时调用, 该方法是客户端与服务端握手成功后调用的方法。 |
@OnOpen |
onError |
当连接过程中异常时调用。 |
@OnError |
服务端如何接收客户端发送的数据呢?
通过为 Session 添加 MessageHandler 消