WebSocket是一种实现全双工通信的网络技术标准,它允许在用户的浏览器和服务器之间进行持久的、双向的通信。以下是对WebSocket的具体介绍:
- 实时性:与传统HTTP请求相比,WebSocket提供了更高效的实时数据交换方式。一旦建立连接,客户端与服务端可以同时相互发送信息,而不需要像HTTP那样每次请求都要重新建立连接。
- 持久连接:WebSocket建立在TCP协议之上,它使用一次“握手”来建立连接,此后便可以在客户端和服务器之间保持一个持久的连接状态,直到其中一方主动关闭连接。
- 低延迟:由于WebSocket支持长连接和双向通信,它可以显著减少网络延迟,尤其适用于需要快速响应的场景,例如在线游戏、实时通知等。
- 轻量级:虽然WebSocket基于HTTP协议,但它有自己的专门协议,这使得它在传输效率上更高,头部信息更小,减少了额外的数据传输开销。
- 兼容性:WebSocket协议得到了现代浏览器的广泛支持,并且由W3C定为标准。同时,它也通过RFC 6455和RFC 7936被IETF确定为标准。
- 适用场景:WebSocket特别适用于那些需要服务器主动向客户端推送数据的应用场景,如聊天室、实时监控图表更新展示等。
首先创建客户端WebSocket:
WebSocketClient.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WS_Client</title>
</head>
<body>
<input id="msg" type="text">
<button onclick="send()">发送消息</button>
</body>
<script>
//连接WebSocket 服务器
const clientId = Math.random().toString(36).substr(2);
const websocket = new WebSocket("ws://localhost:8080/ws/" + clientId);
//监听连接建立成功
websocket.onopen = function (){
console.log("WebSocket建立连接成功……")
}
//监听收到服务端消息
websocket.onmessage = function (event){
console.log(event.data);
}
//发送消息
function send(){
websocket.send(document.getElementById('msg').value);
}
//监听窗口关闭事件,当窗口关闭时主动去关闭webSocket连接
window.onbeforeunload = function (){
websocket.close();
}
</script>
</html>
现在编写服务端WebSocketServe:
引入相关依赖:
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
编写WebSocketServer服务端:
package net.wanho.webSocket;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Component
@ServerEndpoint("/ws/{cid}")
public class WebSocketServer {
//存放会话对象
private static Map<String, Session> sessionMap = new HashMap<>();
/**
* 监听连接建立成功
*/
@OnOpen
public void onOpen(Session session, @PathParam("cid") String cid){
System.out.println("客户端:" + cid + "建立连接……");
sessionMap.put(cid,session);
}
/**
* 监听收到客户端消息
*/
@OnMessage
public void onMessage(String msg,@PathParam("cid") String cid){
System.out.println("这是来自于客户端:" + cid + "的消息:" + msg);
}
/**
* 监听连接关闭
* @param cid
*/
@OnClose
public void onClose(@PathParam("cid") String cid){
System.out.println("连接断开:" + cid);
sessionMap.remove(cid);
}
/**
* 群发消息
*/
public void sendToAllClient(String msg){
Collection<Session> sessions = sessionMap.values();
for (Session session : sessions) {
try {
//服务器向客户端发送消息
session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
编写WebSocket配置类:
/**
* WebSocket配置类,用于注册WebSocket服务端组件
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
编写定时任务,用于向客户端发送信息:
@Component
public class MyWebSocketTask {
@Resource
private WebSocketServer webSocketServer;
/**
* 通过WebSocket每隔5s向客户端发送信息
*/
@Scheduled(cron = "0/3 * * * * ?")
public void sendMessageToClient(){
String format = DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now());
webSocketServer.sendToAllClient("这是来自服务端的消息:" + format);
}
}
在启动类开启定时任务:
@SpringBootApplication
@EnableScheduling //开启定时任务
public class ExcelProjectApplication {
public static void main(String[] args) {
SpringApplication.run(ExcelProjectApplication.class, args);
}
}
测试结果: