当前位置: 首页 > news >正文

websocket(即时通讯)

文章目录

  • 什么是websocket?
  • 代码演示
    • 引入pom文件
    • 新建spring文件夹
      • 创建MyWsConfig
      • 创建SessionBean
      • 创建MyWsHandler
      • 创建MyWsInterceptor
    • 在static文件夹下新建ws-client.html
    • 测试

什么是websocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

为什么有了HTTP协议还要WebSocket

HTTP协议采用的是客户端(浏览器)轮询的方式,即客户端发送请求,服务端做出响应,为了获取最新的数据,需要不断的轮询发出HTTP请求,占用大量带宽。

WebSocket采用了一些特殊的报头,使得浏览器和服务器只需要通过“握手”建立一条连接通道后,此链接保持活跃状态,之后的客户端和服务器的通信都使用这个连接,解决了Web实时性的问题,相比于HTTP有以下好处:

  • 一个Web客户端只建立一个TCP连接
  • WebSocket服务端可以主动推送(push)数据到Web客户端
  • 有更加轻量级的头,减少了数据传输量

特点

  1. 建立在TCP协议只上,服务端比较容易实现
  2. 于HTTP协议有良好的兼容性,默认端口也是80和443,握手阶段使用HTTP协议,因此握手时不容
    易屏蔽,能通过各种HTTP代理服务器
  3. 数据格式轻量,通信高效且节省带宽
  4. 支持传输文本数据和二进制数据
  5. 没有同源限制,客户端可以与任意服务器通信
  6. 也支持加密传输,WS+SSL,URL形如wss://

先建一个springboot项目

代码演示

引入pom文件

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.32</version> <!-- 请使用当前最新稳定版 --><scope>provided</scope>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

新建spring文件夹

com/hsh下新建

创建MyWsConfig

package com.mc.wsdemo.spring;import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import javax.annotation.Resource;@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {@ResourceMyWsHandler myWsHandler;@ResourceMyWsInterceptor myWsInterceptor;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myWsHandler,"/myWs1").addInterceptors(myWsInterceptor).setAllowedOrigins("*");}
}

创建SessionBean

package com.mc.wsdemo.spring;import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.socket.WebSocketSession;@AllArgsConstructor
@Data
public class SessionBean {private WebSocketSession webSocketSession;private Integer clientId;
}

创建MyWsHandler

package com.mc.wsdemo.spring;import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;/*** web socket 主处理程序*/
@Slf4j
@Component
public class MyWsHandler extends AbstractWebSocketHandler {private static Map<String,SessionBean> sessionBeanMap ;private static AtomicInteger clientIdMaker;private static StringBuffer stringBuffer;static {sessionBeanMap = new ConcurrentHashMap<>();clientIdMaker = new AtomicInteger(0);stringBuffer = new StringBuffer();}//连接建立@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {super.afterConnectionEstablished(session);// (会话,id)SessionBean sessionBean = new SessionBean(session,clientIdMaker.getAndIncrement());// 加入map集合sessionBeanMap.put(session.getId(),sessionBean);// 打印日志log.info(sessionBeanMap.get(session.getId()).getClientId()+"建立了连接");// 谁进入群聊  String message = id+进入了群聊stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+"进入了群聊<br/>");// 调用群发的方法  sendMessage(message)sendMessage(sessionBeanMap);}//收到消息@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {super.handleTextMessage(session, message);log.info(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload());// String message = id+"前端发送的消息"stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload()+"<br/>");// 调用群发方法sendMessage(sessionBeanMap);}//传输异常@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {super.handleTransportError(session, exception);if(session.isOpen()){session.close();}sessionBeanMap.remove(session.getId());}//连接关闭@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {super.afterConnectionClosed(session, status);int clientId = sessionBeanMap.get(session.getId()).getClientId();sessionBeanMap.remove(session);log.info(clientId+"关闭了连接");stringBuffer.append(clientId+"退出了群聊<br/>");sendMessage(sessionBeanMap);}//    //每2s发送给客户端心跳消息
//    @Scheduled(fixedRate = 2000)
//    public void sendMsg() throws IOException {
//        for(String key:sessionBeanMap.keySet()){
//            sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage("心跳"));
//        }
//    }/*** 群发方法(包括谁进入聊天室,谁发送了信息,谁退出了聊天室)* @param sessionBeanMap*/public void sendMessage(Map<String,SessionBean> sessionBeanMap){for(String key:sessionBeanMap.keySet()){try {sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(stringBuffer.toString()));} catch (IOException e) {
//                e.printStackTrace();log.error(e.getMessage());}}}
}

创建MyWsInterceptor

package com.mc.wsdemo.spring;import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;import java.util.Map;/*** 握手拦截器*/
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {log.info(request.getRemoteAddress().toString()+"开始握手");return super.beforeHandshake(request, response, wsHandler, attributes);}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {log.info(request.getRemoteAddress().toString()+"完成握手");super.afterHandshake(request, response, wsHandler, ex);}
}

在static文件夹下新建ws-client.html

resources/static文件夹下新建ws-client.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>ws client</title>
</head>
<body>
<p style="border:1px solid black;width: 600px;height: 500px" id="talkMsg"></p>
<input id="message" /><button id="sendBtn" onclick="sendMsg()">发送</button>
</body>
<script>// 给后端发消息说我建立连接let ws = new WebSocket("ws://localhost:8080/myWs1")// ws.onopen=function () {// }// 后端给前端发消息(相当于是前端监听作用,有消息进来就在P标签中  展示)ws.onmessage=function (message) {document.getElementById("talkMsg").innerHTML = message.data}// 前端给后端发消息(点击发送按钮)function sendMsg() {ws.send(document.getElementById("message").value)document.getElementById("message").value=""}
</script>
</html>

测试

输入http://localhost:8080/ws-client.html访问
在这里插入图片描述
在开一个浏览器窗口
在这里插入图片描述

http://www.dtcms.com/a/597788.html

相关文章:

  • 宁波cms建站网站建设的切片是什么
  • 在防火墙环境下进行LoadRunner性能测试的配置方法
  • 企业门户网站开发门户网站英文版建设
  • 【系统架构设计师-2025下半年真题】案例分析-参考答案及详解(回忆版)
  • 在家做私房菜的网站永州本地网站建设
  • MyBatis如何处理懒加载和预加载?
  • 计算机更换硬盘并新装系统
  • 高端营销型企业网站建设wordpress升级vip
  • 使用adb获取安卓模拟器日志
  • GFC-Chain 公链正式连接 GOF4生态体系,开启去中心化生态新篇章
  • PaddleOCR----制作数据集,模型训练,验证 QT部署(未完成)
  • leetcode 474 一和零
  • ADB点击实战-做一个自动点广告播放领金币的脚本app(下)
  • 系统运维Day06_RSYSLOG系统日志管理
  • LeetCodeHot100| 438.找到字符串中所有字符异位次、和为k 的子数组
  • 网络安全与数字化转型的价值投资
  • 免费网站建设教程厦门建站最新消息
  • 电子辐射能量场的具体过程
  • 住房和城乡规划建设局官方网站士兵突击网站怎么做
  • 文件名精灵2025 v1.0
  • 高端品牌型网站建设店面设计多少钱一个平方
  • git仓库管理
  • SSM基于vuejs的图书管理系统171wx(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • Qt 配置Webassemble环境
  • 维力安网站建设公司wordpress 建站 电子书
  • 珠海微信网站上海电商网站开发
  • 成都企业网站的建立网站开发实用技术知识点
  • 网站后台生成html企业培训课程一览表
  • 解锁整车EEA---功能与物理架构的深度剖析
  • 完善EKF可观测性体系:基于ElastAlert2构建k8s智能钉钉日志告警系统