Websocket (帧格式, 握手过程, Spring 中使用 WebScoket 协议)

简介: Websocket (帧格式, 握手过程, Spring 中使用 WebScoket 协议)

什么是 WebSocket

客户端 A 和客户端 B 的消息传播需要借助服务器的中转 (原因是内网不能给另一个局域网的内网直接联通, 需要借助服务器的外网做 “中介”) (NAT 地址转换)

Http 协议 不支持实时通讯 (或者说不支持服务器主动推送数据给客户端)

TCP 本身是具有服务器推送数据这样的功能的, 但是 Http 把它搞丢了 (发明 Http 的大佬们当年所处的时候, 网页就是用来看看新闻, 也没想到后辈能把网页玩出花来)

于是有了 WebSocket 协议.(基于传输层的 TCP 实现) (和 Http 一样, 都是 应用层协议 )

Tomcat 和 Spring 都提供了 WebSocket API, 方便我们通过 WebSocket 协议实现服务器消息推送


Socket 和 WebSocket

Socket 是 OS (或者说传输层) 提供的一组用于网络编程的 API

WebSocket 是一个应用层协议

二者牛马不相及 (没关系)

硬要说有关系, 那就是 WebSocket 的内部实现用到了 Socket

帧格式 (Base Framing Protocol)

FIN : 表示本帧是否是消息的最后一帧, 是1否0

opcode : 解释 payload data 的类型

MASK : 表示 Payload data 是否经过掩码处理

Payload len: 有效载荷长度 ( [0, 125] – 只使用 Payload len空间, [126] – 表示使用 Payload len 和 Extension Payload len 空间, >[127, …] – 使用 Payload len 和 Extension Payload len 和 Extension payLoad len continue 空间) (即不同数值用不同空间来表示载荷的长度)

masking-key : 掩码内容, 当 MASK = 1 时被启用

payload data : 载荷的具体内容

WebSocket 握手过程

握手之前, 客户端和浏览器同为 Http 协议

握手开始, 客户端向服务器发起 Http 请求, 根据请求头里包含的信息, 请求服务器进行协议切换

( Connection: upgrade – 能不能换个协议啊)

( Upgrade: WebSocket – 换成 WebSocket 协议行不行啊)

服务器收到浏览器的请求, 并返回响应, 并切换协议格式

( Connection: upgrade – 能换协议啊)

( Upgrade: WebSocket – 换成 WebSocket 协议 ok 啊)

返回的协议内, 状态码为 101, 明确告诉客户端, 我已经切换协议了, 我们之后用 WebSocket 协议进行通信

WebSocket 和 Http 协议是什么关系?

没关系

Http 就是 工具人

客户端和服务器之间通过 Http 协议建立连接, 连接建立完成之后, 就再也用不到 Http 协议了

WebSocket 在 Spring 中的使用

前端

// 创建 websocket 实例, 或者说进行与服务器建立 WebSocket 连接
// let websocket = new WebSocket("ws://127.0.0.1:8080/WebSocketMessage"); // 操作本地
// let websocket = new WebSocket("ws://152.136.56.110:9090/WebSocketMessage"); //操作远程服务器
let websocket = new WebSocket("ws://" + location.host + "/WebSocketMessage"); //统一格式

websocket.onopen = function() {
  // 该方法在连接建立完成后, 被自动调用
    console.log("websocket 连接成功!");
}

websocket.onmessage = function(e) {
  // 该方法在收到消息时, 被自动调用
    console.log("websocket 收到消息! " + e.data);
    // 处理消息响应
    handleMessage(e.data);  
}

websocket.onclose = function() {
  // 该方法在连接关闭后, 被自动调用
    console.log("websocket 连接关闭!");
}

websocket.onerror = function() {
  // 该方法在连接异常时, 被自动调用
    console.log("websocket 连接异常!");
}

后端

导入依赖

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

首先是 创建 Handler 对象, 让其 继承 TextWebSocketHandler

然后将 Handler 注册到 实现 WebSocketConfigurer 接口 的 注册类中

对于 Handler 对象, 有四个常用的方法

afterConnectionEstablished : 该方法在 WebSocket 连接建立 之后, 被自动调用

handlerTextMessage : 该方法在 WebSocket 收到消息 的时候, 被自动调用

handlerTransportError : 该方法在连接 出现异常 的时候, 被自动调用

afterConnectionClosed : 该方法在连接 正常关闭 后, 被自动调用

@Component
public class TestWebSocketAPI extends TextWebSocketHandler {
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 该方法会在 websocket 连接建立之后, 被自动调用
        System.out.println("Test 连接成功!");
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 该方法会在 websocket 收到消息的时候, 被自动调用
        System.out.println("Test 收到消息!" + message.toString());
    
    // 这里可以直接用, 是因为在注册器中, 已经把 HttpSession 中的内容给放到 WebSocketSession 中了
    User user = session.getAttribute().get("user");

        // session 是个会话, 里面记录通信双方的信息 (session 中持有 websocket 的通信连接)
        session.sendMessage(message);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        // 这个方法实在 连接出现异常的时候, 被自动调用
        System.out.println("Test 连接异常!");
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        // 这个方法是在连接正常关闭后, 会被自动调用
        System.out.println("Test 连接关闭!");
    }
}

对于注册器, 通过 registerWebSocketHandlers 方法的来注册 Handler (记得给注册器添加注解: @EnableWebSocket)

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Autowired
    private TestWebSocketAPI testWebSocketAPI;

    @Autowired
    private WebSocketAPI webSocketAPI;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 通过本方法, 将创建好的 Handler 类给注册到具体路径上.
        // 此时浏览器可通过 请求路径, 调用到绑定的 Handler 类.
        registry.addHandler(testWebSocketAPI, "/test")
                // 通过注册这个特定的 HttpSession 拦截器, 可以把用户在
                // HttpSession 中添加的 Attribute 键值对
                // 往 WebSocketSession 中添加一份
                .addInterceptors(new HttpSessionHandshakeInterceptor());
    }
}

目录
相关文章
|
3月前
|
前端开发 网络协议 JavaScript
在Spring Boot中实现基于WebSocket的实时通信
在Spring Boot中实现基于WebSocket的实时通信
|
21天前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
98 7
Jmeter实现WebSocket协议的接口测试方法
|
1月前
|
机器学习/深度学习 自然语言处理 网络协议
为什么ChatGPT采用SSE协议而不是WebSocket?
在探讨大型语言模型ChatGPT的技术实现时,一个引人注目的细节是其选择使用SSE(Server-Sent Events)协议而非WebSocket来实现数据的实时推送。这一选择背后,蕴含着对技术特性、应用场景及资源效率的深思熟虑。本文将深入探讨ChatGPT为何偏爱SSE,以及这一决策背后的技术逻辑。
49 2
|
29天前
|
JavaScript 前端开发 Java
【颠覆传统】Spring框架如何用WebSocket技术重塑实时通信格局?揭秘背后的故事与技术细节!
【9月更文挑战第4天】随着Web应用对实时交互需求的增长,传统的HTTP模型已无法满足现代应用的要求,特别是在需要持续、双向通信的场景下。WebSocket协议由此诞生,提供全双工通信渠道,使服务器与客户端能实时互发消息。作为Java开发中最受欢迎的框架之一,Spring通过其WebSocket模块支持这一协议,简化了WebSocket在Spring应用中的集成。
40 0
|
2月前
|
JavaScript 前端开发 网络协议
WebSocket在Java Spring Boot+Vue框架中实现消息推送功能
在现代Web应用中,实时消息提醒是一项非常重要的功能,能够极大地提升用户体验。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为实现实时消息提醒提供了高效且低延迟的解决方案。本文将详细介绍如何在Java Spring Boot后端和Vue前端框架中利用WebSocket实现消息提醒功能。
|
4月前
|
前端开发 JavaScript 安全
集成WebSocket在Spring Boot中可以用于实现实时的双向通信
集成WebSocket在Spring Boot中可以用于实现实时的双向通信
76 4
|
4月前
|
网络协议 Java 应用服务中间件
|
3月前
|
监控 网络协议 Java
如何在Spring Boot中使用WebSocket
如何在Spring Boot中使用WebSocket
|
4月前
|
负载均衡 安全 Java
Java一分钟之-WebSocket:实时通信协议
【6月更文挑战第1天】WebSocket是实现客户端与服务器长连接、双向通信的协议,简化实时数据传输。Java中的WebSocket实现基于JSR 356。本文涵盖WebSocket基础(持久连接、双向通信、低延迟)、工作流程、常见问题(安全、连接管理、数据编码)及Java实现示例,强调错误处理、心跳机制和资源管理的最佳实践。
192 6
|
4月前
WebSocket 协议
【6月更文挑战第6天】
28 1
下一篇
无影云桌面