WebSocket | 基于TCP的全双工通信网络协议

文章目录

  • 1、介绍
  • 2、示例
    • 2.1、分析
    • 2.2、代码开发
    • 2.3、功能测试

​🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎Python人工智能开发和前端开发。
🦅主页:@逐梦苍穹
📕所属专栏:Java EE
✈ 您的一键三连,是我创作的最大动力🌹

1、介绍

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

  • HTTP是短连接,WebSocket是长连接
  • HTTP通信是单向的,基于请求响应模式;WebSocket支持双向通信
  • HTTP和WebSocket底层都是TCP连接
    在这里插入图片描述

**思考:**既然WebSocket支持双向通信,功能看似比HTTP强大,那么我们是不是可以基于WebSocket开发所有的业务功能?

WebSocket缺点:

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

结论: WebSocket并不能完全取代HTTP,它只适合在特定的场景下使用

WebSocket应用场景:

1). 视频弹幕
2). 网页聊天
3). 体育实况更新
4). 股票基金报价实时更新

2、示例

2.1、分析

**需求:**实现浏览器与服务器全双工通信。浏览器既可以向服务器发送消息,服务器也可主动向浏览器推送消息。
效果展示:
在这里插入图片描述

实现步骤:

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

2.2、代码开发

1). 定义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);

    //判断当前浏览器是否支持WebSocket
    if('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>

2). 导入maven坐标

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

3). 定义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();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客户端:" + sid + "建立连接");
        sessionMap.put(sid, session);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @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) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

4). 定义配置类,注册WebSocket的服务端组件

package com.sky.config;

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 {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

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

package com.sky.task;

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 {
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 通过WebSocket每隔5秒向客户端发送消息
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMessageToClient() {
        webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
    }
}

2.3、功能测试

启动服务,打开websocket.html页面
浏览器向服务器发送数据:
在这里插入图片描述

服务器向浏览器间隔5秒推送数据:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/388665.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习---HMM前向、后向和维特比算法的计算

1. HMM import numpy as np# In[15]:class HiddenMarkov:def forward(self, Q, V, A, B, O, PI): # 使用前向算法N len(Q) # 状态序列的大小M len(O) # 观测序列的大小alphas np.zeros((N, M)) # alpha值T M # 有几个时刻&#xff0c;有几个观测序列&#xff0c;就有…

智慧职教考试怎么搜题找答案? #微信#其他

下面将介绍一些大学生常用的日常学习辅助工具和资料&#xff0c;希望能为你的学习提供帮助和便利 1.题老大 这个是公众号 内容很丰富&#xff0c;范围包括公考、计算机、建筑工程、会计资格、消防、外语外贸、教师资格&#xff01; 下方附上一些测试的试题及答案 1、带式输…

[OPEN SQL] 更新数据

UPDATE语句用于更新数据库表中的数据 本次操作使用的数据库表为SCUSTOM&#xff0c;其字段内容如下所示 航班用户(SCUSTOM) 需要操作更新以下数据 1.更新单条数据 语法格式 UPDATE <dbtab> FROM <wa>. UPDATE <dbtab> FROM TABLE <itab>. UPDATE &l…

【机器学习笔记】4 朴素贝叶斯

贝叶斯方法 贝叶斯分类 贝叶斯分类是一类分类算法的总称&#xff0c;这类算法均以贝叶斯定理为基础&#xff0c;故统称为贝叶斯分类。 朴素贝叶斯分类是这一类算法中最简单的较为常见的算法。 先验概率 根据以往经验和分析得到的概率。我们用&#x1d443;(&#x1d44c;)来代…

MySQL 基础知识(六)之数据查询(二)

目录 6 数值型函数 7 字符串函数 8 流程控制函数 9 聚合函数 10 分组查询 (group by) 11 分组过滤 (having) 12 限定查询 (limit) 13 多表查询 13.1 连接条件关键词 (on、using) 13.2 连接算法 13.3 交叉连接 (cross join) 13.4 内连接 (inner join) 13.5 外连接 …

Redis.conf 配置文件解读

1、单位 容量单位不区分大小写&#xff0c;G和GB没有区别 配置文件 unit单位 对大小写不敏感 2、组合配置 可以使用 include 组合多个配置问题 3、网络配置 bind 127.0.0.1 # 绑定的ip protected-mode yes # 保护模式 port 6379 # 端口设置4、通用 GENERAL daemoniz…

第13讲我创建的投票列表实现

新建我创建的投票页面 {"path": "pages/createVoteList/createVoteList","style": {"navigationBarTitleText": "我创建的投票"}}个人中心页面&#xff0c;加下 点击 “我创建的投票”跳转列表页面 goVoteList:function(){u…

linux 09 软件安装,YUM

下载软件时候&#xff0c;windows会从网上下载exe文件。 windows中的exe文件linux中的rpm文件 简介部分&#xff1a; 其中的认识RPM包&#xff1a; YUM&#xff08;软件包管理工具&#xff09; 01.YUM工具简介 02.使用YUM 第一 安装YUM 全新安装&#xff1a; 01.先pin…

统计图饼图绘制方法(C语言)

统计图饼图绘制方法&#xff08;C语言&#xff09; 常用的统计图有条形图、柱形图、折线图、曲线图、饼图、环形图、扇形图。 前几类图比较容易绘制&#xff0c;饼图绘制较难。今值此介绍饼图的绘制方法。 本方法采用C语言的最基本功能&#xff1a; &#xff08; 1.&#xff09…

嵌入式STM32 单片机 GPIO 的工作原理详解

STM32的 GPIO 介绍 GPIO 是通用输入/输出端口的简称&#xff0c;是 STM32 可控制的引脚。GPIO 的引脚与外部硬件设备连接&#xff0c;可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 以 STM32F103ZET6 芯片为例子&#xff0c;该芯片共有 144 脚芯片&#xff0c…

(15)Hive调优——数据倾斜的解决指南

目录 前言 一、什么是数据倾斜 二、发生数据倾斜的表现 2.1 MapReduce任务 2.2 Spark任务 三、如何定位发生数据倾斜的代码 四、发生数据倾斜的原因 3.1 key分布不均匀 3.1.1 某些key存在大量相同值 3.1.2 存在大量异常值或空值 3.2 业务数据本身的特性 3.3 SQL语句…

关于npmlink的问题

深入浅出关于Npm linl的问题 关键词&#xff1a; vue3报错 Uncaught TypeError: Cannot read properties of null (reading ‘isCE‘) at renderSlot npm link 无法实现热更新 我的开发环境是 “vue”: “^3.2.13” 今天在使用 rollup搭建组件库的时候我发现我的组件库不能…

C语言:指针的基础详解

目录 1. 内存 2. 取地址& 3. 指针变量 4. 解引用 4.1 *解引用 4.2 []解引用 4.3 ->解引用 5. 指针变量的大小 5.1 结论 6. 指针运算 7. void* 指针 8. const修饰指针 8.1 const修饰变量 8.2 const修饰指针变量 8.3 结论 9. 野指针 9.1 为什么会出现野指…

计网体系结构

计算机网络的概述 概念 网络&#xff1a;网状类的东西或系统。 计算机网络&#xff1a;是一个将分散的、具有独立性功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。即计算机网络是互连(通过通信链路互连…

Go语言的100个错误使用场景(40-47)|字符串函数方法

前言 大家好&#xff0c;这里是白泽。 《Go语言的100个错误以及如何避免》 是最近朋友推荐我阅读的书籍&#xff0c;我初步浏览之后&#xff0c;大为惊喜。就像这书中第一章的标题说到的&#xff1a;“Go: Simple to learn but hard to master”&#xff0c;整本书通过分析100…

ClickHouse--03--数据类型

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 数据类型1. Int2.FloattoFloat32(...) 用来将字符串转换成 Float32 类型的函数toFloat64(...) 用来将字符串转换成 Float64 类型的函数 3.DecimaltoDecimal32(value…

微服务中台架构的设计与实现

本文将探讨微服务中台架构的设计与实现&#xff0c;介绍如何通过微服务的方式进行系统拆分和组合&#xff0c;构建灵活、可扩展且易于维护的中台架构&#xff0c;以加速企业的数字化转型和提升竞争力。 ## 1. 引言 随着企业规模的不断扩大和业务的日益复杂化&#xff0c;传统…

RabbitMQ配置消息转换器

1. 默认转换器 Test public void testSendMap() throws InterruptedException {// 准备消息Map<String, Object> msg new HashMap<>();msg.put("name", "harry");msg.put("age", 21);// 发送消息rabbitTemplate.convertAndSend(&q…

问题:规范化过程主要为克服数据库逻辑结构中的插入异常、删除异常以及(??)的缺陷. #职场发展#职场发展#知识分享

问题&#xff1a;规范化过程主要为克服数据库逻辑结构中的插入异常、删除异常以及(??)的缺陷. 参考答案如图所示

JVM内存模型深度剖析与优化

JDK体系结构 Java语言的跨平台特性 JVM整体结构及内存模型 补充一个问题&#xff1a; 在minor gc过程中对象挪动后&#xff0c;引用如何修改&#xff1f; 对象在堆内部挪动的过程其实是复制&#xff0c;原有区域对象还在&#xff0c;一般不直接清理&#xff0c;JVM内部清理过程…
最新文章