WebSocket
1.1 WebSocket介绍
WebSocket 是一种网络通信协议。RFC6455定义了他的通信标准。
WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。
HTTP协议是一种无状态的、无连接的、单项的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求作出应答处理。
这种通信模型有一个弊端:HTTP协议无法实现服务器主动向客户端发送消息。
这种单项请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数Web应用程序将通过频繁的异步AJAX请求实现长轮询。轮序的效率低,非常浪费资源(因为必须不停连接,或者HTTP连接始终打开)。
http协议:
1.2 WebSocket协议
本协议有两部分:握手和数据传输。
握手就是基于http协议的。
来自客户端的额握手看起来如下格式:
服务器的握手看起来像如下形式:
字段说明:
头名称 | 说明 |
---|
Connection:Upgrade | 表示该HTTP请求是一个协议升级请求 | Upgrade:WebSocket | 协议升级为WebSocket协议 | Sec-WebSocket-Version:13 | 客户端支持WebSocket的版本 | Sec-WebSocket-Key: | 客户端采用base64编码的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对象.onclsoe | 连接关闭时触发 |
1.3.3 WebSocketfangaf
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 注解指定接收消息的方法。
服务端如何推送数据给客户端呢?
发送消息则有 RemoteEndpoint 完成,其实例由 Session 维护,根据使用情况,我们可以通过 Session.getBasicREmote 获取同步消息发送的实例,然后调动其sendXXX()方法就可以发送消息,可以通过Session.getAsyncRemote获取异步消息发送实例。
服务端代码:
@ServerEndpoint("/robin")
public clas testWSChatEndPoint{
private static Set<testWSChatEndPoint> webSocket = new HashSet<>();
private Session session;
@onMessage
public void onMessage(String message, Session session) throws IOException{
System.out.println("接收的消息是:" + message);
System.out.println(session);
for(Chat chat : webSocketSet){
if(chat != this){
chat.session.getBasicRemote().sendText(message);
}
}
}
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketSet.add(this);
}
@OnClose
public void onClose(Session session){
System.out.prinln("连接关闭了。。。");
}
@OnError
public void onError(Session session,Throwable error){
System.out.println("出错了,错误信息:"+error.getMessage());
}
}
rror public void onError(Session session,Throwable error){ System.out.println(“出错了,错误信息:”+error.getMessage()); } }
摘录自:https://www.bilibili.com/video/BV1r54y1D72U
|