大家好,又见面了,我是你们的朋友全栈君。
之前所有的请求都是浏览器发起,浏览器本身没有接受请求的能力。所以一些特殊需求都是用ajax轮询的方式来实现的。
比如:
HTML5推广之后,服务端主动推送数据,浏览器接受数据的方式来解决
全双工就是双向通信,WebSocket就是移动电话(可以随时发送信息与接受信息,就是全双工)
本质上是一个额外的TCP连接,建立和关闭时握手使用HTTP协议,其他数据传输不使用HTTP协议
HTML5新标准,用来从服务端实时推送数据到浏览器端,直接建立在当前HTTP连接上 本质上是保持一个HTTP长连接、轻量协议。
=》 客户端发送一个请求 到服务端,服务端保持这个请求连接知道一个新的消息准备好,将消息返回到客户端。除非主动关闭,否则一直保持连接。
SSE一大特色: 重复利用1个连接来接受服务器发送的消息(event),从而避免不断轮询请求建立连接,造成服务资源紧张。
是否基于新协议 | 是否双向通信 | 是否支持跨域 | |
---|---|---|---|
SSE | 否(Http) | 否(单向) | 否(Firefox 支持跨域) |
WebSocket | 是(ws) | 是 | 是 |
Eg: 淘宝买一个产品之后进行扫码支付,结合SSE实现这个过程
对于服务器端像浏览器发送的数据,浏览器端需要在JavaScript中使用EventSource对象来进行处理。EventSource使用的是标准的事件监听器方式,只需要在对象上添加相应事件处理方法。
事件名称 | 事件触发说明 | 事件处理方法 |
---|---|---|
open | 当服务器向浏览器第一次发送数据时产生 | onopen |
message | 当收到服务器发送的消息时产生 | onmessage |
error | 当出现异常时产生 | onerror |
一旦你的项目里面使用了https协议,你的websocket就要使用wss协议才可以。怎么让Spring Boot项目支持WSS协议?
socket = new WebSocket("wss://localhost:8888/ws/asset");
@Component
@Slf4j
@ServerEndpoint(value = "/ws/asset")
public class WebSocketServer{
}
WebSocketServer本节内容的核心代码,websocket服务端代码
@ServerEndpoint(value = “/ws/asset”)表示websocket的接口服务地址 @OnOpen注解的方法,为连接建立成功时调用的方法 @OnClose注解的方法,为连接关闭调用的方法 @OnMessage注解的方法,为收到客户端消息后调用的方法 @OnError注解的方法,为出现异常时调用的方法
@Component
@Slf4j
@ServerEndpoint(value = "/ws/asset")
public class WebSocketServer {
//用来统计连接客户端的数量
private static final AtomicInteger OnlineCount = new AtomicInteger(0);
// concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。
private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) throws IOException {
SessionSet.add(session);
int cnt = OnlineCount.incrementAndGet(); // 在线数加1
log.info("有连接加入,当前连接数为:{}", cnt);
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
log.info("来自客户端的消息:{}",message);
sendMessage(session, "Echo消息内容:"+message);
// broadCastInfo(message); 群发消息
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
SessionSet.remove(session);
int cnt = OnlineCount.decrementAndGet();
log.info("有连接关闭,当前连接数为:{}", cnt);
}
/**
* 出现错误
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误:{},Session ID: {}",error.getMessage(),session.getId());
}
/**
* 发送消息,实践表明,每次浏览器刷新,session会发生变化。
* @param session session
* @param message 消息
*/
private static void sendMessage(Session session, String message) throws IOException {
session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId()));
}
/**
* 群发消息
* @param message 消息
*/
public static void broadCastInfo(String message) throws IOException {
for (Session session : SessionSet) {
if(session.isOpen()){
sendMessage(session, message);
}
}
}
}
客户端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>websocket测试</title>
<style type="text/css">
h3,h4{
text-align:center;
}
</style>
</head>
<body>
<h3>请输入要发送给服务器端的消息:</h3><br/>
<label for="text">输入发送信息</label><input id="text" type="text" />
<button onclick="sendToServer()">发送服务器消息</button>
<button onclick="closeWebSocket()">关闭连接</button>
<br>
信息:
<span id="message">
</span>
<script type="text/javascript">
var socket;
if (typeof (WebSocket) == "undefined") {
console.log("遗憾:您的浏览器不支持WebSocket");
} else {
socket = new WebSocket("wss://localhost:8888/ws/asset");
//连接打开事件
socket.onopen = function() {
console.log("Socket已打开");
};
//收到消息事件
socket.onmessage = function(msg) {
document.getElementById('message').innerHTML += msg.data + '<br/>';
};
//连接关闭事件
socket.onclose = function() {
console.log("Socket已关闭");
};
//发生了错误事件
socket.onerror = function() {
alert("Socket发生了错误");
};
//窗口关闭时,关闭连接
window.unload=function() {
socket.close();
};
}
//关闭连接
function closeWebSocket(){
socket.close();
}
//发送消息给服务器
function sendToServer(){
var message = document.getElementById('text').value;
socket.send(message);
}
</script>
</body>
</html>
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/155724.html原文链接:https://javaforall.cn