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

网络协议 WebSocket

一、介绍

WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输

1、HTTP协议和WebSocket协议对比

  • HTTP 是短连接
  • WebSocket 是长连接
  • HTTP 通信是单向的,基于请求响应模式
  • WebSocket 支持双向通信
  • HTTP 和 WebSocket 底层都是 TCP 连接

2、缺点

  • 服务器长期维护长连接需要一定的成本
  • 各个浏览器支持程度不一
  • WebSocket 是长连接,受网络限制比较大

二、使用

实现浏览器与服务器全双工通信。浏览器既可以向服务器发送消息,服务器也可主动向浏览器推送消息

1、实现步骤

  1. 直接使用 websocket.html 页面作为 WebSocket 客户端
  2. 导入 WebSocket 的 maven 坐标
  3. 导入 WebSocket 服务端组件 WebSocketServer,用于和客户端通信
  4. 导入配置类 WebSocketConfiguration,注册 WebSocket 的服务端组件
  5. 导入定时任务类 WebSocketTask,定时向客户端推送数据

2、代码开发

websocket.html

<!DOCTYPE HTML>
<html>
<head><meta charset="UTF-8"><title>WebSocket Demo</title>
</head>
<body><input id="text" type="text" /><button onclick="send()">发送消息</button><button onclick="closeWebSocket()">关闭连接</button><div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;var clientId = Math.random().toString(36).substr(2);//判断当前浏览器是否支持WebSocketif('WebSocket' in window){//连接WebSocket节点websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);}else{alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function(){setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(){setMessageInnerHTML("连接成功");}//接收到消息的回调方法websocket.onmessage = function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function(){setMessageInnerHTML("close");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function(){websocket.close();}//将消息显示在网页上function setMessageInnerHTML(innerHTML){document.getElementById('message').innerHTML += innerHTML + '<br/>';}//发送消息function send(){var message = document.getElementById('text').value;websocket.send(message);}//关闭连接function closeWebSocket() {websocket.close();}
</script>
</html>

maven 坐标

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

定义 WebSocket 服务端组件

package com.sky.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.util.Collection;
import java.util.HashMap;
import java.util.Map;/*** WebSocket服务*/
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {//存放会话对象private static Map<String, Session> sessionMap = new HashMap();/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {System.out.println("客户端:" + sid + "建立连接");sessionMap.put(sid, session);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, @PathParam("sid") String sid) {System.out.println("收到来自客户端:" + sid + "的信息:" + message);}/*** 连接关闭调用的方法** @param sid*/@OnClosepublic void onClose(@PathParam("sid") String sid) {System.out.println("连接断开:" + sid);sessionMap.remove(sid);}/*** 群发** @param message*/public void sendToAllClient(String message) {Collection<Session> sessions = sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}
}

定义配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** WebSocket配置类,用于注册WebSocket的Bean*/
@Configuration
public class WebSocketConfiguration {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

定义定时任务类,定时向客户端推送数据

import com.sky.websocket.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 {@Autowiredprivate WebSocketServer webSocketServer;/*** 通过WebSocket每隔5秒向客户端发送消息*/@Scheduled(cron = "0/5 * * * * ?")public void sendMessageToClient() {webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));}
}
http://www.lryc.cn/news/235026.html

相关文章:

  • 路径操作 合法路径名
  • JavaEE初阶 01 计算机是如何工作的
  • 【shell 常用脚本30例】
  • 【我和Python算法的初相遇】——体验递归的可视化篇
  • 【C语言的秘密】密探—深究C语言中多组输入的秘密!
  • ClickHouse 语法优化规则
  • 3-运行第一个docker image-hello world
  • 【漏洞复现】泛微e-Weaver SQL注入
  • 「git 系列」git 如何存储代码的?
  • IDEA 集成 Docker 插件一键部署 SpringBoot 应用
  • IDEA无法查看源码是.class,而不是.java解决方案?
  • 机器视觉系统选型-定光照强度
  • ChatGLM3-6B:新一代开源双语对话语言模型,流畅对话与低部署门槛再升级
  • StoneDB顺利通过中科院软件所 2023 开源之夏 结项审核
  • Linux本地docker一键部署traefik+内网穿透工具实现远程访问Web UI管理界面
  • SpringCloud FeignClient声明式服务调用采坑记录(A调用服务B/C,B/C重启后必须重启A后才能成功调用配置项)
  • 安装银河麒麟linux系统docker(docker-compose)环境,注意事项(一定能解决,有环境资源)
  • BUG:编写springboot单元测试,自动注入实体类报空指针异常
  • 深度解析 InterpretML:打开机器学习模型的黑箱
  • 数据结构初阶leetcodeOJ题(二)
  • 若依框架数据源切换为pg库
  • java 访问sqlserver 和 此驱动程序不支持jre1.8错误
  • C/C++字符判断 2021年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
  • Kotlin语言实现单击任意TextVIew切换一个新页面,并且实现颜色变换
  • Flume学习笔记(4)—— Flume数据流监控
  • 使用webhook发送企业微信消息
  • C语言的由来与发展历程
  • python django 小程序博客源码
  • Android并发编程与多线程
  • ChatGPT简介及基本概念