说明:本文对WebSocket不做深入的讲解,编写此文的主要目的是明白程序的过程。可以参考实例化代码看上面的描述,这样会很容易理解。
WebSocket通常用于网站的通信模块,可以实现后端管理页面的消息的推送。情景分析:客户想知道当前最新的订单消息,同时希望听到提醒的消息(类似美团后台提醒一样)。类似这种需求就可以利用H5 WebSocket技术去实现。最终效果图类似下图:
那么,什么是WebSocket?
答:WebSocket 是一种自然的全双工、双向、单套接字连接。使用WebSocket,你的HTTP 请求变成打开WebSocket 连接的单一请求,并且重用从客户端到服务器以及服务器到客户端的同一连接。WebSocket 减少了延迟,因为一旦建立起WebSocket 连接,服务器可以在消息可用时发送它们。类似利用手机通话,只要建立起连,那么就可以双方互相通话。我们都知道HTTP协议是无状态的协议,那么要实现这样的功能肯定用的不是HTTP协议了,那么这里用又是什么协议?在这里建立连接使用的是WS,其实就是把HTTP换为WS,URL没有发生实质性的变化。
ws://r9rkvd.natappfree.cc/sell/webSocket
WebSocket的工作流程是什么?
答:WebSocket 接口规定了可用于客户端的方法以及客户端与网络的交互方式。首先,你要调用WebSocket 构造函数(constructor),创建一个WebSocket 连接。构造函数返回WebSocket 对象实例。你可以监听该对象上的事件,这些事件告诉你何时连接打开,何时消息到达,何时连接关闭以及何时发生错误。你可以与WebSocket 对象交互,发送消息或者关闭连接。
既然要监听事件,那么在WebWebSocket中有些什么事件?
答:只要WebSocket连接打开,应用程序就简单地监听事件,监听的时候只需要调用与之对应的函数就可以了。在WebSocket中有4个调度对象,分别是:open(打开连接)、message(推送的消息)、error(错误故障)、close(关闭连接)。在前端监听的时候是可以使用<on>+名称来触发该事件。
那这4个事件的执行流程是什么?
首先创建一个WebSocket对象,请求服务器建立一个连接,一旦服务器响应了WebSocket 连接请求,open 事件触发并建立一个连接。在后端里面主要就是将当前会话,丢进WebSocket容器中,方便后期直接使用。到open 事件触发时,协议握手已经完成,WebSocket 已经准备好发送和接收数据。如果应用程序接收到一个open 事件,那么可以确定WebSocket 服务器成功地处理了连接请求,并且同意与应用程序通信。然后发送消息,其中消息包含来自服务器任何类型的数据。在服务器端需遍历Socket容器中的连接,然后将消息逐条发送
webSocket.session.getBasicRemote().sendText(message);在业务需要的地方可以直接调用该方法,完成数据的发送。最后就是关闭会话,关闭连接。
后端是如何提供服务的?
本文使用的是SpringBoot,因此采用注解的方式实现管理。首先需要创建一个通信对象,使用@Component注解把普通pojo实例化到spring容器中,方便后期的维护与管理,提供了访问此项服务的地址,使用@ServerEndpoint("/webSocket")注解提供访问入口。当socket容器建立好之后,可以直接使用@OnOpen、@OnClose、@OnMessage注解,对容器里面的连接做修改。最后需要广播发送消息。
实例化代码:
1.导入Socket依赖
<!--socket依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.配置Socket(主要就是实例化对象,便于连接使用)
@Component
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
3.前端请求连接与监测
<script>
var websocket = null;
// 判断浏览器有没有通信功能
if ('WebSocket' in window) {
//创建一个通信对象(ws协议)
websocket = new WebSocket('ws://r9rkvd.natappfree.cc/sell/webSocket')
} else {
alert("您的浏览器不支持通信功能,请更换最新浏览器尝试!");
}
//windows事件
websocket.onopen = function (e) {
console.log('建立连接');
}
websocket.onclose = function (e) {
console.log('关闭连接');
}
websocket.onmessage = function (e) {
//可以是(消息,图片、音乐)
console.log('收到的消息' + e.data);
$('deepModal').showModal('show');
document.getElementById('notice').play();
}
websocket.onerror = function (e) {
console.log('通信错误!')
}
// 当浏览器关闭的时候同时也关闭通信
websocket.onbeforeunload = function (e) {
websocket.close();
}
</script>
4.提供服务对象
@Component
@ServerEndpoint("/webSocket")
@Slf4j
public class WebSocket {
/** 创建一个会话*/
private Session session;
/***创建一个session容器 */
private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();
/**
* 打开连接
* @param session
*/
@OnOpen
public void onOpen(Session session){
this.session = session;
webSockets.add(this);
log.info("【webSocket消息】 有新的连接,总数:{}",webSockets.size());
}
/**
* 断开连接的使用
*/
@OnClose
public void onClose(){
webSockets.remove(this);
log.info("【webSocket消息】连接断开,总数:{}",webSockets.size());
}
/**
* 通信消息
* @param message
*/
@OnMessage
public void onMessage(String message){
log.info("【webSocket消息】收到客户端的消息;{}",message);
}
/**
* 广播发送消息
* @param message
*/
public void sendMessage(String message){
for(WebSocket webSocket: webSockets){
try {
webSocket.session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}