websocket通信协议

使用场景==========================================

        先说明客户端-服务器已经可以通过http进行通信了,为什么还要使用通过websocket,http协议局限:http协议是基于请求-响应的,也就是说只有客户端发起了请求,服务端才能回应,服务端无法主动给客户端发送消息。

        那这样可不行,服务端想要主动给客户端发送消息怎么办,比如说:后台系统出现问题怎么通知客户端,客户端-服务器想要建立聊天会话怎么实现,订单状态的变更如何让客户端知晓等

Server to Client的常见实现方式========================

  • 长轮询(Long Polling):简单易实现,兼容性好,但效率低,延迟高。适用于不频繁需要实时数据更新的应用。
    • 实现原理:客户端通过不断轮询请求服务端接口达到长连接的效果
  • 服务器发送事件(Server-Sent Events, SSE):简单易用,支持自动重连,适用于实时数据更新和持续数据推送的应用,但仅支持单向通信。
    • 实现原理:通过特定请求头告诉服务器,客户端希望以事件流的形式接收数据,服务端会保持连接开放状态。
  • WebSocket:支持双向通信,低延迟,高效传输,适用于高频实时交互和需要实时通知更新的应用。
    • 实现原理:通过一次握手建立持久连接

Websocket的实现--springboot=========================

1.引入依赖

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

2.配置websocket

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfiguration {

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

}

3.创建工具类方便后续使用

import javax.websocket.Session;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebSocketUtils {

    private static final Map<String, Session> sessions = new ConcurrentHashMap<>();

    public static void addSession(String sessionId, Session session) {
        sessions.put(sessionId, session);
    }

    public static void removeSession(String sessionId) {
        sessions.remove(sessionId);
    }
    
    //给某个客户端发送消息
    public static void sendMessageToSession(String sessionId, String message) {
        Session session = sessions.get(sessionId);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    //群发
    public static void sendMessageToAll(String message) {
        sessions.values().forEach(session -> {
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

4.端点类中注册会话--就是在这里处理和客户端的消息

WebSocket 服务器可以同时与多个客户端建立连接并进行独立管理。

每个连接都有一个独立的会话session,通过 sessionId 进行标识

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

//websocket端点url
@ServerEndpoint("/ws")
public class WebSocketServer {

    //初始建立连接的处理
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("Connected: " + session.getId());
        WebSocketUtils.addSession(session.getId(), session);
        WebSocketUtils.sendMessageToSession(session.getId(), "Welcome to the WebSocket server!");
    }
    
    //接收到客户端消息的处理
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("Received: " + message);
        WebSocketUtils.sendMessageToSession(session.getId(), "Server received: " + message);
    }
    
    //连接关闭的处理
    @OnClose
    public void onClose(Session session) {
        System.out.println("Disconnected: " + session.getId());
        WebSocketUtils.removeSession(session.getId());
    }
    
    //连接错误的处理
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.err.println("Error for session " + session.getId() + ": " + throwable.getMessage());
        WebSocketUtils.removeSession(session.getId());
    }
}

5.如果要给客户端发送消息:

import org.springframework.stereotype.Service;

@Service
public class NotificationService {

     

    public void notifyClient(String sessionId, String message) {
        //发送给某一个连接
        WebSocketUtils.sendMessageToSession(sessionId, message);
    }

    public void notifyAllClients(String message) {
        //发送给所有的连接
        WebSocketUtils.sendMessageToAll(message);
    }
}

前端vue中与服务端建立连接并发送或接收消息示例代码:

 methods: {
    connectWebSocket() {
      // 创建 WebSocket 连接,这里写的是服务端websocket端点url
      this.socket = new WebSocket('ws://localhost:8080/ws');

      // WebSocket 连接成功时触发
      this.socket.onopen = () => {
        console.log('WebSocket connection established');
      };

      // 接收到服务器消息时触发
      this.socket.onmessage = (event) => {
        this.serverMessage = event.data;
      };

      // WebSocket 连接关闭时触发
      this.socket.onclose = () => {
        console.log('WebSocket connection closed');
      };

      // WebSocket 连接发生错误时触发
      this.socket.onerror = (error) => {
        console.error('WebSocket error:', error);
      };
    },
    sendMessage() {
      // 向服务器发送消息
      if (this.socket && this.socket.readyState === WebSocket.OPEN) {
        this.socket.send(this.message);
      }
    },
}

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值