Websocket实现消息实时推送流程

本文介绍了WebSocket的概念、原理,以及如何在智能预约系统中实现消息的实时推送和连接的管理,包括心跳机制确保连接稳定性。重点展示了WebSocket的双向通信、持久连接特性在提高效率和减少资源消耗中的作用。
摘要由CSDN通过智能技术生成

一、前言

        在开发智能预约系统中,我们经常会遇到这样一类需求:用户需要远程预约,预约屏需要实时显示会议预约信息或者实时预约顺序等实时变化的数据。对于此类需求,传统的请求方式就是轮询,就是客户端通过一定时间间隔以频繁请求方式向服务器发送请求,来保持客户端和服务器端的数据同步。但这种做法有一个很大的弊端:当客户端已固定频率向服务器发送请求时,服务器端的数据可能并没有更新,带来很多不必要的请求,浪费带宽,效率低下;不频繁的话,数据更新可能又不及时。

二、Websocket概念以及原理

2.1定义

        WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

  • WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;
  • WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

2.2原理图

2.2.1连接的建立----三次握手


     

        第一次握手:客户端向服务器端发送SYN包,表示“请求建立新连接”,客户端进入SYN_SENT状态。

        第二次握手:服务器端收到SYN包,确认客户端发送过来的报文有效,服务器能正常接收客户端发送的数据,并向客户端发送SYN + ACK包,表示“同意建立新连接”。服务器端进入SYN_RECV状态。

        第三次握手:客户端收到服务器端的SYN+ACK包,随后向服务器端发送ACK确认包,表示“确认收到服务器端同意连接的信号”,客户端和服务器端进入ESTABLISHED状态,建立连接完成。

        三次握手的过程中,只能由客户端主动向服务器端发送连接请求,而服务器端则是被动接受连接请求。通过三次握手,双方确保彼此能够正常建立连接,数据交互正常。

        SYN:同步序列号,用于建立会话连接。

        ACK:确认数据包。

        SYN_SENT:请求连接状态。

        SYN_RECV:数据接收状态。

        ESTABLISHED:建立连接状态。

2.2.2连接的结束----四次挥手

        第一次挥手:客户端发起关闭连接请求,向服务器端发送FIN包,表示客户端不再接收发送数据,客户端进入FIN_WAIT_1状态。

         第二次挥手:服务器端确认关闭连接请求,向客户端发送一个ACK确认报文,表示已经接收到客户端发送的关闭请求,服务器端进入CLOSE_WAIT状态。

         第三次挥手:服务器端在发送完全部数据后,向客户端发送一个FIN包,表示不再接收发送数据,服务器端进入LAST_ACK

         第四次挥手:客户端收到服务器端发送的FIN包后,向服务器端发送一个ACK确认报文,表示客户端接受关闭连接请求,客户端进入超时等待状态。随后服务器端进入CLOSED状态,连接关闭完成。

        四次挥手的过程中,任何一方都可以发起关闭请求,另一方则必须对其进行确认,确保双方都完成关闭连接。

        FIN:结束报文。

        FIN_WAIT_1:等待关闭确认状态。

        CLOSE_WAIT:被动等待关闭状态。

        LAST_ACK:等待确认状态。

        CLOSED:关闭状态。

        等待超时时间的作用:如果客户端发送完最后一个ACK包之后,就释放连接资源,一旦ACK在发送的过程中出现网络丢失的情况,服务器端没有收到确认消息,那么就会一直处于最后确认状态,无法关闭连接。等待超时状态可以很好的解决这个问题,服务器端没有收到ACK包后,会重新发送FIN包,此时客户端还处于连接状态,向服务器端重新发送ACK包。

三、Websocket实现消息实时推送-----以预约系统为例

3.1客户端建立连接

var websocket = null;

// 判断当前浏览器是否支持WebSocket, ws对应的地址是远程服务器端的请求路径
if ('WebSocket' in window) {
    websocket = new WebSocket("ws://localhost:8010/websocket");  // 客户端建立连接请求
} else {
    console.error("不支持WebSocket");
}

3.2服务器端建立连接

@RestController
@RequestMapping("/websocket")

/* 
 @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,注解的值将被用于监听设备连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端。
*/
@ServerEndpoint(value = "/websocket/{macAddress}")

public class WebSocketServer {

    @Autowired
    private reservationService reservation;  // 预约信息Service层

    
    @Autowired
    private deviceService device;             // 设备信息Service层

    /**
     * 设备MAC地址的Map集合,key:MAC地址,value:Session对象
     */
   private static Map<String, Session> sessionMap = new HashMap<String, Session>();
 
   @OnOpen
   public void onOpen(Session session, @PathParam("macAddress") String macAddress) {
        
        // 将设备添加到设备列表
        sessionMap.put(macAddress, session);


        // 从数据库中获取保存的预约信息
        List<Reservation> list= reservation.selectReservation();

        // 向设备发送预约数据
        sendMessageToDevice(macAddress,list);
        

    }

}

3.3向特定设备发送消息

    // 向特定设备发送消息------根据设备的唯一标识(MAC地址),向特定设备发送消息
    public static void sendMessageToDevice(String macAddress, List<Reservation> dataList) {
        Session session = devices.get(macAddress);
        if (session != null && session.isOpen()) {
            try {

                /*使用了Jackson库的ObjectMapper来将List 类型的数据转换为 JSON 格式。
                在sendMessageToDevice方法中,我们将传入的 List 数据转换为 JSON 格式的字符串,并通过 WebSocket 发送给特定的设备。
                */
                String jsonData = objectMapper.writeValueAsString(dataList);
                session.getBasicRemote().sendText(jsonData);
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

3.4设备接收服务器端发送的数据

// 处理 WebSocket 连接
websocket.on('connection', function connection(ws) {

   ws.on('open', function open() {
          
        console.log('已连接到服务器');

         // 在连接建立后,启动心跳定时器
         startHeartbeat();
  });

  // 接收消息
  ws.on('message', function incoming(message) {

    if(message === 'ok'){

         console.log('服务器端发送过来的数据是: %s', message);

        // 收到心跳消息,向服务器发送心跳回复消息
        sendHeartbeat();

    }else{

        // 将预约信息进行展示

    }

  });

});

function sendHeartbeat() {
  // 向服务器发送心跳回复消息
  ws.send('ok');
}

function startHeartbeat() {
  // 每隔一段时间发送一次心跳消息
  setInterval(() => {
    ws.send('ok');
  }, 10000); // 10秒发送一次心跳消息
}

3.5处理设备发送过来的消息

@OnMessage
 public void onMessage(String message) {

    System.out.println("收到客户端发来的消息是: " + message);


   // 首先回复客户端处于运行状态
   if ("ok".equals(message)) {

            // 收到心跳消息,回复服务器端
            sendHeartbeat(session);

        } else {
            // 处理其他消息
            
           // 进行人脸识别操作

           // 二维码扫描验证操作

           // 密码验证操作等等

     }

}

private void sendHeartbeat(Session session) {
        try {
            session.getBasicRemote().sendText("ok");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3.5与设备断开连接

@OnClose
public void onClose(Session session, @PathParam("macAddress") String macAddress) {
        // 将设备从设备列表中移除
        sessionMap.remove(macAddress);

        // 根据下线的设备MAC地址,修改数据库中设备的状态码----以便于后台系统实时监测设备的在线情况
        device.update(macAddress);
}

四、如何监听设备是否处于在线情况!

        基于Websocket的心跳机制来实现。Websocket的心跳机制是为了保持连接的稳定性和可靠性而设计的。在Websocket通信过程中,客户端和服务器之间会定期发送心跳消息来确认连接是否仍然有效。

具体的心跳机制可以通过以下步骤实现:

  1. 客户端和服务器建立Websocket连接后,客户端会定时发送一个心跳消息给服务器。
  2. 服务器接收到心跳消息后,会立即回复一个心跳响应消息给客户端。
  3. 客户端接收到心跳响应消息后,可以确认连接仍然有效,并继续发送其他的业务消息。
  4. 如果客户端在一定时间内没有收到服务器的心跳响应消息,就可以认为连接已经断开或者出现了异常情况。
  5. 当客户端检测到连接异常时,可以进行相应的处理,比如重新建立连接或者进行其他的错误处理。
  6.  通过心跳机制,可以及时检测到连接的异常情况,并采取相应的措施来保持连接的稳定性。同时,心跳机制也可以用来监控连接的质量和性能,以便及时发现和解决潜在的问题。

五、小结

        WebSocket 是一种在 Web 应用程序中实现双向通信的协议,它具有双向通信、持久连接、低延迟、安全性等特性,适用于实时应用程序和需要实时数据更新的场景。全双工通信以及持久性连接特点使得WebSocket在在线聊天、实时游戏、股票行情推送方面频繁使用,这些应用要求数据实时更新,每次通信不需要重新建立连接,减少了通信的开销并提高了通信效率。

  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue2若依项目中实现前端WebSocket实时推送可以通过以下步骤进行: 1. 安装依赖:首先,你需要安装WebSocket相关的依赖库。Vue2若依项目中常用的WebSocket库有sockjs和stompjs。可以通过以下命令进行安装: ```bash npm install sockjs-client stompjs --save ``` 2. 创建WebSocket连接:在需要使用WebSocket的组件中,可以创建一个WebSocket连接。例如: ```javascript import SockJS from 'sockjs-client' import Stomp from 'stompjs' export default { data() { return { stompClient: null } }, methods: { connect() { const socket = new SockJS('/ws') // WebSocket端点,根据后端配置进行调整 this.stompClient = Stomp.over(socket) this.stompClient.connect({}, this.onConnected, this.onError) }, onConnected() { // 连接成功回调函数 this.stompClient.subscribe('/topic/yourTopic', this.onMessageReceived) }, onError(error) { // 连接错误回调函数 console.error(error) }, onMessageReceived(message) { // 接收到消息回调函数 const data = JSON.parse(message.body) // 处理接收到的消息 } }, mounted() { this.connect() }, beforeDestroy() { if (this.stompClient) { this.stompClient.disconnect() } } } ``` 3. 发送消息:如果需要向服务器发送消息,可以调用`this.stompClient.send(destination, headers, body)`方法发送消息。其中,`destination`为目标地址,`headers`为请求头,`body`为消息体。 4. 接收消息:在`onMessageReceived`回调函数中处理接收到的消息。根据实际情况,可以将消息存储到Vue组件的data中,并在模板中进行展示。 5. 后端配置:确保后端服务器(如Spring Boot)配置了WebSocket支持,并提供了相应的WebSocket端点。 以上是在Vue2若依项目中实现前端WebSocket实时推送的简单流程和代码示例。具体的配置和实现方式可能会因项目的具体需求和后端技术栈而有所不同,请根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值