WebSocket 是一种基于 TCP 协议的全双工通信协议,它允许客户端和服务器之间建立持久的、双向的通信连接。相比传统的 HTTP 请求 - 响应模式,WebSocket 提供了实时、低延迟的数据传输能力。通过 WebSocket,客户端和服务器可以在任意时间点互相发送消息,实现实时更新和即时通信的功能。WebSocket 协议经过了多个浏览器和服务器的支持,成为了现代 Web 应用中常用的通信协议之一。它广泛应用于聊天应用、实时数据更新、多人游戏等场景,为 Web 应用提供了更好的用户体验和更高效的数据传输方式。
项目的弹幕系统设计用WebSocket来实现,用户评论弹幕,然后将数据推送到前端去。
网站实时在线人数也可以,每次登录的时候和服务器建立socket连接,当关闭的时候socket连接退出。可以统计网站的实时在线人数。
浏览器和服务器可以实现双向的数据传输。
http协议和websocket协议的区别
http 是短链接 webSocket是长连接
Http是单项的,基于请求响应模式 websocket支持双向通信
http和websocket底层都是基于TCP连接
应用
视频弹幕 网页聊天
体育实况更新,页面没有刷新,实时展示出来的。
股票基金报价实时更新
后端项目中应用websocket
项目中,导入 starter 坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
创建配置类
通过配置类,注册 webSocket 的 Bean 实列
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* WebSocket配置类,用于注册WebSocket的Bean。注册Bean
*/
@Configuration
public class WebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
HTTP 请求接收使用的是 RestController
@ServerEndpoint(“/ws/{sid}”)
package com.njitzx.controller;
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.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {
//存放会话对象 存放会话对象
private static Map<String, Session> sessionMap = new HashMap();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
System.out.println("客户端:" + sid + "建立连接");
sessionMap.put(sid, session);
}
/**
* 收到客户端消息后调用的方法 类似于Controller的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, @PathParam("sid") String sid) {
System.out.println("收到来自客户端:" + sid + "的信息:" + message);
}
/**
* 连接关闭调用的方法
*
* @param sid
*/
@OnClose
public void onClose(@PathParam("sid") String sid) {
System.out.println("连接断开:" + sid);
sessionMap.remove(sid);
}
//实现广播的消息
/**
* 群发
*
* @param message
*/
public void sendToAllClient(String message) {
//将前端传过来的数据群发, 所有人都能拿到会话 values拿到map集合的所有属性值
Collection<Session> sessions = sessionMap.values();
for (Session session : sessions) {
try {
//服务器向客户端发送消息
session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
定时任务处理消息。比如弹幕消息。每隔几秒钟就向前端进行推送。
package com.njitzx;
import com.njitzx.controller.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class WebSocketTask {
@Autowired
private WebSocketServer webSocketServer;
/**
* 通过WebSocket每隔5秒向客户端发送消息
*/
@Scheduled(cron = "0/5 * * * * ?")
public void sendMessageToClient() {
webSocketServer.sendToAllClient("这是来自服务端的消息 外卖超时了老哥:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
}
}
·
vue3 前端使用 websocket
<script setup>
import {nextTick, onMounted, onUnmounted} from "vue";
import {ElNotification} from "element-plus";
import {test} from "@/api/camera/camera";
let ws=null
onMounted(() => {
//可以传入用户的唯一ID
const sid = '123' // 你实际项目中根据需要进行修改
//创建websocket链接 实际地址应该是代理地址
ws = new WebSocket(`ws://localhost:8088/ws/${sid}`)
// 连接打开
ws.onopen = () => {
}
// 收到后端推送的消息
ws.onmessage = (event) => {
const msg = event.data
console.log('从后端收到的消息:', msg)
// 使用 Element Plus Notification 进行右上角弹窗
ElNotification({
title: '风机预警',
message: msg,
position: 'top-right',
type:'error',
duration: 3000 // 3 秒后自动关闭,可自行调整
})
}
// 连接被关闭
ws.onclose = () => {
console.log('WebSocket 连接已关闭')
}
// 如果需要监听错误
ws.onerror = (error) => {
console.log('WebSocket 发生错误:', error)
}
})
//离开页面的时候关闭websocket连接
onUnmounted(() => {
// 当离开页面或关闭应用时,主动关闭连接
if (ws) {
ws.close()
console.log('主动关闭 WebSocket 连接')
}
})
const test1=async ()=>{
await test()
}
</script>
<template>
<div>
<el-button @click="test1()"></el-button>
<!-- 首页正在开发中-->
</div>
</template>
<script>
</script>