1、WebSocket
1.1、WebSocket介绍
WebSocket是一种网络通信协议。DEC6455 定义了它的通信标准。
WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。
HTTP协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求
做出应答处理。
这种通信模型有一一个弊端: HTTP 协议无法实现服务器主动向客户端发起消息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数web应用程序将通过频繁的异步
AJAX请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者HTTP连接始终打开)。

特点:
其特点包括:
- (1)建立在TCP协议上,服务器端的实现比较容器。
 - (2)与HTTP协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用HTTP协议,因此握手时不容易屏蔽,能通过各种HTTP代理服务器。
 - (3)数据格式比较轻量化,性能开销小,通信高效
 - (4)可以发送文本,也可以发送二进制数据
 - (5)没有同源限制,客户端可以与任意服务器通信
 
1.2 websocket协议
本协议有两部分:握手和数据传输。
握手是基于http协议的。
来自客户端的握手看起来像如下形式:
1| GET ws://localhost/chat HTTP/1.1
2| Host: localhost
3| Upgrade: websocket
4| Connection: Upgrade
5| Sec-web Socket-Key: dGh1IHNhbXB sZSBub25jZQ==
6| Sec -Websocket- Extensions: pe rmessage-deflate
7| Sec -Websocket-Version: 13
来自服务器 的握手看起来像如下形式:
HTTP/1.1 101 Switching Protocols
upgrade: websocket
connection: Upgrade
Sec -Web Socket- Accept: s3pPLMBi TxaQ9kYGzzhZRbK+x00=
Sec-Wwebsocket-Extensi ons: permessage-deflate
字段说明:
| 头名称 | 说明 | 
|---|---|
| Connection : Upgrade | 标识该HTTP请求是一一个协议升级请求 | 
| Upgrade : WebSocket | 协议升级为webSocke t协议 | 
| Sec-WebSocket - Version: 13 | 客户端支持webSocket的版本 | 
| Sec-WebSocket - Key : | 客户端采用base6 4编码的24位随机字符序列,服务器接受客户端HTTP协议升级的证明。要求服务端响应一个对应加密的Sec-WebSocket -Accept头信息作为应答 | 
| Sec-WebSocket - Extensions | 协议扩展类型 | 
1.3、客户端(浏览器)实现
1.3.1、websocket对象
实现webSockets的Web浏览器将通过webSocket对象公开所有必需的客户端功能(主要指支持Html5 的浏览器)。
以下API用于创建WebSocket 对象:
var ws = new WebSocket(url)
- 参数url说明:ws://ip地址:端口号/资源名称
 
1.3.2、websocket事件
WebSocket对象相关事件
| 事件 | 事件处理程序 | 描述 | 
|---|---|---|
| open | WebSocket对象.onopen | 连接建立时触发 | 
| message | WebSocket对象.onmessage | 客户端接收服务端数据时触发 | 
| error | WebSocket对象.onerror | 通信发生错误时触发 | 
| close | WebSocket对象.onclose | 连接关闭时触发 | 
1.3.3、WebSocket方法
WebSocket 对象的相关方法
| 方法 | 描述 | 
|---|---|
| send() | 使用连接发送数据 | 
1.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消息处理器来接收消息,当采用注解方式定义Endpoint时,我们还可以通过
@OnMessage注解指定接收消息的方法。
服务端如何推送数据给客户端呢?
发送消息则由RemoteErpdpoint 完成,其实例由 Session 维护,根据使用情况, 我们可以通过
Session. getBasicRemote获取同步消息发送的实例,然后调用其 sendXxX ()方法就可以发送消息,可以通过
Session. getAsyncRemote获取异步消息发送实例。
2.2、实验流程

2.3、消息格式
客户端 –> 服务器
{“toName”:”张三”,”message”:”你好”}
服务端 –> 客户端
- 系统消息格式:{“isSystem”:true,”fromName”:null,”message”:[“李四”,”王五”]}
 - 推送给某一个的消息格式: { “isSystem” : false, “ fromName”: “张三”, “message”: “你好”}