【网络协议】WebSocket讲解

目录

webSocket简介

连接原理解析:

客户端API

服务端API(java)

实战案例

(1)引入依赖

(2)编写服务端逻辑

(3)注册配置类

[(4)前端连接 WebSocket 示例](#(4)前端连接 WebSocket 示例)

Websocket与其他消息推送对比

总结


大家好,我是jstart千语。相信大家或多或少都听说过webSocket,与http协议都是TCP下的一种通信协议。主要用于客户端和服务端可以相互通信的协议,与http协议不同,http协议只能由客户端想服务端发送请求后,服务端才能向客户端响应消息。而webSocket协议却可以主动向客户端发送消息,这就是全双工通信。


webSocket简介

WebSocket 是一种基于 TCP 的网络通信协议,设计用于在客户端(通常是浏览器)和服务器之间建立一个持久化的、双向通信通道。记住最主要的一句话就可以了:实时通信。

传统的 HTTP 协议是 请求-响应模式,不适合实时性要求高的应用。而 WebSocket 允许服务器主动向客户端推送消息,非常适合用于聊天室、在线游戏、股票行情、实时通知等场景。

全双工与半双工通信的区别:

|-----|----------------------------------|
| 半双工 | 允许数据在两个方向上传输,但同一个时间段内只允许一个方向上的传输 |
| 全双工 | 允许数据在两个方向上同时传输 |

特点:

WebSocket 是一种基于 TCP 的双向通信协议,它与 HTTP 一样在应用层运行,但一旦连接建立,通信通道就会一直保持开启。

它具备以下特点:

  • 全双工通信:客户端和服务端都可以主动发送消息

  • 长连接:连接建立后无需频繁重连

  • 低延迟:没有 HTTP 多次握手的开销

  • 浏览器支持广泛:现代浏览器均已支持

连接原理解析:

  1. 首先还是会通过TCP的三次握手来建立连接
  2. 先由http发送一次请求,请求携带对应的请求头,告诉服务端要升级协议
  3. 如果服务端支持该协议,也响应对应的响应头,并且响应状态码设置为101,表示要切换协议
  4. 协议切换成功后,就可以使用webSocket进行双向通信了

建立流程示例:

客户端API

示例:

javascript 复制代码
<script>
    let ws = new WebSocket("ws://localhost/chat")
    ws.onopen = function(){

    };
    ws.onmessage = function(evt){
        //通过evt.data 可以获取服务器发送的数据
    };
    ws.onclose(){
    
    };

<script>

服务端API(java)

Tomcat的7.0.5版本开始支持WebSocket,并且实现了Java WebSocket规范。

Java WebSocket应用由一系列的Endpoint组成。Endpoint是一个java对象,代表WebSocket链接的一端,对于服务端,我们可以视为处理具体WebSocket消息的接口。

其中,Endpoint对象就是客户端与服务端建立连接时就创建的一个对象, 一个客户端对应一个Endpoint对象。每个客户端建立时都会创建一个。

Endpoint有两种定义方式:编程试和注解试:

|---------|------------------------------------|----------|
| onOpen | 当开启一个新的会话时调用,该方法是客户端与服务端握手成功后调用的方法 | @onOpen |
| onClose | 当会话关闭时调用 | @onClose |
| onError | 当连接过程异常时调用 | @onError |

如何向客户端发送消息?

发送消息则由 RemoteEndpoint完成,其实例由 Session维护。

通过session.getBasicRemote获取同步消息 发送的实例,然后调用其sendXxx()方法发送消息 通过session.getAsyncRemote获取异步消息发送实例,然后调用其sendXxx()方法发送消息



实战案例

(1)引入依赖

XML 复制代码
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

(2)编写服务端逻辑

java 复制代码
@ServerEndpoint("/ws/chat")
@Component
public class ChatEndpoint {

    private static final Set<Session> sessions = ConcurrentHashMap.newKeySet();

    @OnOpen
    public void onOpen(Session session) {
        sessions.add(session);
        System.out.println("用户连接: " + session.getId());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("收到消息: " + message);
        // 广播给所有人
        for (Session s : sessions) {
            s.getAsyncRemote().sendText(message);
        }
    }

    @OnClose
    public void onClose(Session session) {
        sessions.remove(session);
        System.out.println("用户断开: " + session.getId());
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.err.println("错误: " + error.getMessage());
    }
}

(3)注册配置类

这个类用于识别扫描所有添加了webSocket相关注解的类

java 复制代码
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

(4)前端连接 WebSocket 示例

javascript 复制代码
<script>
  const socket = new WebSocket("ws://localhost:8080/ws/chat");

  socket.onopen = () => {
      console.log("连接已建立");
      socket.send("你好 WebSocket!");
  };

  socket.onmessage = (event) => {
      console.log("收到消息: " + event.data);
  };

  socket.onclose = () => {
      console.log("连接关闭");
  };
</script>


Websocket与其他消息推送对比

轮询方式最常见的就是扫码登录流程了,当用户页面出现一个二维码时

轮询:每隔一两秒,向服务端发送一次请求,识别该二维码有没有被扫描到,服务端响应对应的消息。缺点:当用户正好在发送某次请求后扫码,那用户也要等一两秒后才能被响应,会有明显卡顿。

长轮询:客户端想服务端发送一次请求,当服务端有数据变更时,二维码被扫描到,或者请求超时时(一般是30s)才返回信息。


SSE也是支持长连接的,也使用与服务端主动进行消息推送,但浏览器的支持没有webSocket好。而且通信也是单向的。



总结

WebSocket 是现代实时 Web 应用的重要基石,尤其在 Java 后端系统中,可以轻松通过 Spring Boot 快速构建支持高并发、低延迟的通信模块。

  • 加入权限验证(如 token 登录校验)

  • 使用 STOMP 协议进行消息分发与订阅

  • 集成 SockJS 以兼容不支持 WebSocket 的客户端

相关推荐
feng_you_ying_li2 小时前
linux之数据链路层
linux·网络·智能路由器
国科安芯5 小时前
人在回路中的总线:商业空间站环境控制与生命保障系统CANFD网络的可靠性与功能安全
网络·嵌入式硬件·安全·架构·php·抗辐射
国科安芯6 小时前
算力上天之后的电与静:星上边缘计算载荷带外管理网络的低功耗调度与辐射容错
网络·人工智能·嵌入式硬件·安全·边缘计算·低轨卫星·商业航天
wdeok6 小时前
Socket编程UDP-简单的聊天室
网络·网络协议·udp
QXWZ_IA11 小时前
定位数据怎么推给 IoT 平台?消息协议选型与接入准备
网络·人工智能·物联网·安全
wdeok11 小时前
Socket编程Tcp
服务器·网络·tcp
xiaoye-duck1 天前
《C++ 项目:手写大模型接入 SDK》Ollama接口设计(上):初始化、全量响应实现和测试
开发语言·网络·c++·语言模型
无足鸟ICT1 天前
【RHCA+】iptraf-ng(网络监控分析)
linux·网络
坤坤子吖1 天前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习
xiaoye-duck1 天前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型