Websocket——心跳检测

news2025/2/24 18:01:06

1. 前言:为什么需要心跳机制?

        在现代的实时网络应用中,保持客户端和服务端的连接稳定性是非常重要的。尤其是在长时间的网络连接中,存在一些异常情况,导致服务端无法及时感知到客户端的断开,可能造成不必要的资源浪费,甚至是服务端的潜在错误。为了避免这种情况,我们需要一种机制来确保连接的有效性,这就是“心跳机制”。

心跳机制的必要性

        心跳机制的作用在于周期性地检测连接是否仍然活跃。简单来说,心跳就像人类的心跳一样,不断“跳动”,如果在规定的时间内没有收到心跳信号,服务端就可以判断客户端可能已经断开连接,从而主动释放资源或者做出其他处理。

异常断开连接的场景

        在正常情况下,前端和后端的连接断开是可以通过调用相关方法来通知对方的。例如,当用户关闭浏览器或者点击“退出”按钮时,前端可以主动向服务端发送断开连接的请求,服务端也可以通过监听断开事件来进行清理工作。

        然而,如果用户的浏览器突然崩溃、网络中断或者关闭页面时,前端无法发送断开请求,服务端也无法及时感知到客户端已经下线。在这种情况下,服务端就需要一个手段来周期性地检查连接是否还存在。

服务端如何通过心跳保持客户端状态

        为了应对这种情况,心跳机制便应运而生。心跳的基本原理是客户端定时发送一个简单的信号(通常是一个空的数据包)到服务端。服务端通过检测这个信号是否按时到达来判断客户端是否仍然连接。如果在规定时间内没有收到心跳包,服务端就认为该客户端可能已经断开,并可以主动关闭连接或执行其他操作。

        Netty 作为一个高性能的网络框架,内置了非常方便的心跳机制实现工具——IdleStateHandler。通过这个工具,开发者可以非常方便地设置心跳检测的时间间隔,以及如何处理空闲状态,从而确保网络连接的健康和稳定。

小结

        心跳机制在分布式应用、即时通讯、在线游戏等场景中是非常关键的,它帮助服务端及时发现并处理客户端断开的情况,避免资源的浪费和潜在的服务异常。接下来,我们将深入介绍 Netty 如何利用心跳机制来维持连接的稳定性。

2. Netty 心跳机制的实现原理

        Netty 提供了 IdleStateHandler 组件,它是处理心跳机制的关键工具。这个处理器能够帮助我们自动监测连接的空闲状态,并且根据设定的时间间隔触发心跳事件,从而帮助服务端检测客户端是否还保持连接。

2.1 IdleStateHandler 的作用

IdleStateHandler 是 Netty 提供的一个特殊的 ChannelHandler,主要作用是根据指定的时间,自动检测连接的空闲状态。它通过配置三个时间参数来定义空闲状态:

  • readerIdleTime:如果在指定的时间内没有读取到数据,触发空闲事件;
  • writerIdleTime:如果在指定的时间内没有写入数据,触发空闲事件;
  • allIdleTime:如果在指定的时间内既没有读也没有写,触发空闲事件。

通常情况下,我们会使用 readerIdleTime 来进行心跳检测。也就是说,客户端需要定期发送数据包(通常是心跳包)给服务端,确保在规定时间内,服务端能够检测到客户端的活动。如果服务端在设定的时间内没有收到心跳包,就会触发相应的空闲事件(如 IdleStateEvent),然后服务端可以采取关闭连接等措施。

2.2 工作原理

Netty 的心跳机制的工作过程通常如下:

  1. 客户端:每隔一定时间(如 10 秒),客户端向服务端发送一个“心跳包”,该包通常是一个简单的请求或一个空的数据包,目的是告诉服务端“我还活着”。
  2. 服务端:服务端在接收到客户端的心跳包后,更新连接的活跃状态,并且继续等待客户端的心跳信号。
  3. 超时检测:如果在规定的时间(如 30 秒)内,服务端没有收到客户端的心跳包,就会触发 IdleStateEvent,并根据配置的事件类型,执行相关的处理逻辑。
  4. 断开连接:当服务端检测到客户端超过了心跳的最大空闲时间后,会主动断开连接,释放资源,避免无效连接占用资源。

2.3 Netty 实现步骤

通过 IdleStateHandler 实现心跳机制的步骤如下:

  1. 创建 IdleStateHandler:在管道(Pipeline)中添加 IdleStateHandler,并配置读、写或总空闲时间。
  2. 自定义事件处理器:当空闲时间触发时,IdleStateHandler 会触发 IdleStateEvent 事件,开发者可以通过自定义事件处理器来处理这些事件。
  3. 关闭连接:当空闲事件触发时,服务端可以根据具体的业务逻辑决定是否关闭连接或执行其他操作。

2.4 IdleStateHandler 配置实例

        假设我们希望每 30 秒检测一次连接,如果 30 秒内没有收到客户端的数据(读空闲),则认为该连接不再活跃,主动断开连接。那么我们可以在 Netty 服务器的 ChannelPipeline 中这样配置:

// 30秒内没有读数据即认为连接空闲,触发读空闲事件
pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));

在这里,30 表示如果在 30 秒内没有接收到任何读操作的数据包,Netty 会触发一个 IdleStateEvent,而 0 表示我们不关心写空闲和总空闲的状态。

小结

        通过 IdleStateHandler,Netty 提供了非常便捷的机制来处理心跳事件,确保服务端能够及时发现客户端是否断开。接下来的部分,我们将更深入地探讨如何自定义事件处理器,以及如何根据空闲事件的触发来处理连接的关闭或其他业务逻辑。

3. 自定义处理空闲事件

        在使用 IdleStateHandler 配置了心跳检测后,我们需要编写一个自定义的事件处理器来响应空闲事件的触发。这个处理器将会监听并处理由 IdleStateHandler 触发的 IdleStateEvent,并根据实际需求采取相应的操作。

3.1 IdleStateEvent 介绍

IdleStateEvent 是 Netty 提供的一个事件对象,表示连接进入了空闲状态。它由 IdleStateHandler 触发,常见的事件类型有:

  • reader_idle:表示连接在指定的时间内没有读取到任何数据,即“读取空闲”;
  • writer_idle:表示连接在指定的时间内没有写入任何数据,即“写入空闲”;
  • all_idle:表示连接在指定的时间内既没有读也没有写,即“完全空闲”。

通常我们关心的主要是 reader_idle 类型的事件,因为我们希望通过客户端定期发送心跳包,服务端来验证连接是否活跃。

3.2 自定义事件处理器 NettyWebSocketServerHandler

        接下来,我们编写一个 NettyWebSocketServerHandler 类,来处理客户端的请求并处理空闲事件。

public class NettyWebSocketServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 这里可以处理业务逻辑,比如接收来自客户端的数据包
        super.channelRead(ctx, msg);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // 判断是否是 IdleStateEvent 空闲事件
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            
            // 处理读空闲事件
            if (event.state() == IdleState.READER_IDLE) {
                System.out.println("连接空闲,关闭连接:无数据读取!");
                
                // 如果超时没有读数据,认为该连接断开,关闭连接
                ctx.close();  // 关闭连接
            }
        }
    }
}

在上面的代码中,我们实现了 userEventTriggered 方法来处理 IdleStateEvent 事件。当事件类型为 READER_IDLE(即读取空闲事件)时,我们输出日志并关闭连接。此时,服务端通过调用 ctx.close() 关闭连接,释放相关资源。

3.3 将 NettyWebSocketServerHandler 添加到管道

        在 Netty 服务器的 ChannelPipeline 中,添加自定义的 NettyWebSocketServerHandler 处理器,使得它能处理客户端的空闲事件。

public class NettyWebSocketServer {

    public void start() throws InterruptedException {
        // 设置事件处理器链
        EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 用于接收客户端连接
        EventLoopGroup workerGroup = new NioEventLoopGroup(); // 用于处理读写操作

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline pipeline = ch.pipeline();

                     // 添加空闲状态检测处理器,配置30秒没有读操作触发事件
                     pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
                     // 添加自定义的事件处理器来处理空闲事件
                     pipeline.addLast(new NettyWebSocketServerHandler());
                 }
             });

            // 绑定端口,启动服务器
            b.bind(8090).sync().channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

ChannelInitializer 中,我们首先添加了 IdleStateHandler,配置了读空闲的时间为 30 秒。然后,我们添加了自定义的 NettyWebSocketServerHandler 来处理空闲事件。

3.4 处理空闲事件后进行用户下线操作

        除了关闭连接外,我们还可以在空闲事件发生时进行更复杂的操作,例如清理用户会话、推送离线通知等。

        假设我们有一个用户管理的类来保存当前活跃的 WebSocket 连接,当连接空闲时,我们不仅关闭连接,还可以将该用户从在线列表中移除。

public class UserManager {
    private static Map<String, Channel> activeUsers = new ConcurrentHashMap<>();

    public static void addUser(String userId, Channel channel) {
        activeUsers.put(userId, channel);
    }

    public static void removeUser(String userId) {
        activeUsers.remove(userId);
    }
}

public class NettyWebSocketServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            
            if (event.state() == IdleState.READER_IDLE) {
                // 这里假设可以通过 channel 获取用户的 ID
                String userId = (String) ctx.channel().attr(UserSession.USER_ID).get();

                System.out.println("用户 " + userId + " 超时,关闭连接!");
                
                // 移除该用户
                UserManager.removeUser(userId);

                // 关闭连接
                ctx.close();
            }
        }
    }
}

在这个修改版的 NettyWebSocketServerHandler 中,我们假设每个连接都有一个 userId,通过 channelattr 方法获取用户 ID,断开连接时将该用户从 UserManager 中移除。

小结

        Netty 的心跳机制和空闲事件处理功能非常强大,它通过 IdleStateHandler 自动检测连接的空闲状态,帮助服务端发现和处理长时间不活动的客户端连接。通过自定义的事件处理器,我们可以在空闲事件触发时,进行连接关闭、资源清理、用户下线等操作,确保服务器能够及时响应并释放资源。

4. 心跳机制的优化与扩展

        在实现了基本的心跳检测后,我们可以进一步对心跳机制进行优化和扩展。心跳机制的设计不仅仅是为了检测连接是否存活,还可以用于其他优化,例如:

4.1 调整心跳时间间隔

        默认情况下,我们在 Netty 服务器端设置了 IdleStateHandler(30, 0, 0),即 30 秒内没有收到客户端的消息,就会触发 READER_IDLE 事件。但在实际应用中,我们可以根据业务需求调整心跳的频率:

  • 如果服务器的负载较高,可以适当增加心跳间隔,例如 1 分钟检测一次,减少无用的心跳消息,降低服务器压力。
  • 如果对在线状态的准确性要求较高,可以缩短心跳间隔,例如 10~15 秒检测一次,以便尽快发现连接异常。

心跳间隔需要根据实际业务进行权衡:间隔太短会增加服务器负担,间隔太长可能会导致掉线检测不及时

4.2 采用双向心跳

        目前我们的设计是 由客户端定期发送心跳包,服务器被动检测。但在一些场景下,例如 移动端网络不稳定、浏览器休眠、弱网环境等,可能会导致客户端心跳发送失败或延迟。为此,我们可以采用 双向心跳 机制,即:

  • 客户端主动发送心跳(例如每 10 秒发送一次)。
  • 服务器也定期主动向客户端发送心跳请求,如果客户端在规定时间内没有响应,则认为连接已断开。

这样可以 确保双向通信的可靠性,避免单方面心跳导致的误判。

4.3 结合 Redis 或数据库存储用户在线状态

        在多服务器(集群)环境下,单个服务器维护的连接信息可能会不够准确。例如,某个用户可能已经断线,但由于服务器没有立即感知,导致用户状态仍然是“在线”。
为了解决这个问题,我们可以:

  • 将用户的心跳时间存入 Redis,每次收到心跳更新 Redis 中的时间戳。
  • 其他服务器可以通过 Redis 检测用户是否长时间没有发送心跳,从而更准确地判断用户在线状态。

这样,即使用户的 WebSocket 连接在某个服务器上断开了,整个系统仍然可以通过 Redis 统一管理用户的在线状态

4.4 结合 Netty 的自定义 ChannelHandler

除了 IdleStateHandler 之外,我们还可以自定义一个 HeartbeatHandler 来进行更加灵活的心跳控制。例如:

  • 记录心跳次数,如果 连续 3 次心跳超时,才真正断开连接,避免短暂的网络抖动影响用户体验。
  • 结合 流量控制,如果服务器在高负载状态下,可以适当放宽心跳检测标准,防止误判导致大规模掉线。

        通过这些优化,我们可以让 心跳机制更加智能、灵活、稳定,提高 WebSocket 连接的可靠性,为后续的即时通讯、推送等功能提供坚实的基础。

5. 具体实现心跳检测

        在前面的介绍中,我们提到了 Netty 提供的 IdleStateHandler 组件,它可以帮助我们 检测连接是否空闲。现在,我们来看它的 具体实现

5.1 服务器端的心跳检测

        在 NettyWebSocketServer 中,我们已经添加了 IdleStateHandler(30, 0, 0),即 如果 30 秒内没有收到客户端的消息,就会触发 READER_IDLE 事件
但是,仅仅触发事件是不够的,我们还需要在 Handler 中监听这个事件,并进行相应的处理。

步骤 1:继承 SimpleChannelInboundHandler<TextWebSocketFrame>

我们需要自定义一个 NettyWebSocketServerHandler用于处理心跳事件WebSocket 消息

public class NettyWebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;

            if (event.state() == IdleState.READER_IDLE) {
                System.out.println("【心跳超时】关闭连接:" + ctx.channel().remoteAddress());
                ctx.channel().close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        System.out.println("收到消息:" + msg.text());
        ctx.writeAndFlush(new TextWebSocketFrame("服务器已收到消息"));
    }
}

代码解析

  1. 监听 IdleStateEvent 事件

    • event.state() == IdleState.READER_IDLE 说明 30 秒内没有收到消息,意味着客户端可能已经断线,我们就 手动关闭连接
  2. 处理正常的 WebSocket 消息

    • channelRead0 方法用于处理 客户端发来的普通消息,这里简单打印出来,并返回一个 确认消息

5.2 客户端的心跳发送

        为了防止服务器误判掉线,客户端需要定期发送心跳消息。
前端(JavaScript)可以这样实现:

let socket = new WebSocket("ws://localhost:8090/ws");

socket.onopen = function () {
    console.log("WebSocket 连接成功");
    setInterval(() => {
        if (socket.readyState === WebSocket.OPEN) {
            socket.send("ping");
        }
    }, 10000); // 每 10 秒发送一次心跳
};

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

socket.onclose = function () {
    console.log("WebSocket 连接关闭");
};

代码解析

  1. 建立 WebSocket 连接,监听 onopen 事件。
  2. 每 10 秒发送 "ping" 消息,保持连接活跃。
  3. 监听服务器的 onmessage 事件,打印服务器返回的消息。
  4. 监听 onclose 事件,一旦连接断开,前端可以尝试重新连接。

6. 服务器如何区分心跳和普通消息?

channelRead0 方法中,我们目前对所有消息都进行了打印和回写。
但在实际应用中,我们需要 区分普通消息和心跳消息,避免误处理:

@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
    String text = msg.text();
    if ("ping".equals(text)) {
        System.out.println("收到客户端心跳");
        ctx.writeAndFlush(new TextWebSocketFrame("pong")); // 返回心跳确认
    } else {
        System.out.println("收到普通消息:" + text);
        ctx.writeAndFlush(new TextWebSocketFrame("服务器已收到消息:" + text));
    }
}

改进点

  1. 如果收到 "ping",说明是 心跳消息,直接返回 "pong",避免误处理。
  2. 如果收到普通消息,进行正常的逻辑处理。

7. 心跳机制测试

  1. 正常连接时

    • 前端每 10 秒发送 "ping",服务器返回 "pong",连接保持活跃。
  2. 如果前端关闭网页

    • 服务器在 30 秒后触发 READER_IDLE 事件,自动断开连接。
  3. 如果网络异常

    • 服务器仍然可以在 30 秒后感知到超时,并清理资源,保证不会有 无效连接 长时间占用服务器资源。

         这样,我们就完成了 基于 Netty 的 WebSocket 心跳检测,并且实现了 前端心跳发送、后端心跳检测、心跳超时处理等功能

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于YOLO11深度学习的半导体芯片缺陷检测系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

Spring Boot3.x集成Flowable7.x(一)Spring Boot集成与设计、部署、发起、完成简单流程

一、Flowable简介 Flowable 是一个轻量级、开源的业务流程管理&#xff08;BPM&#xff09;和工作流引擎&#xff0c;旨在帮助开发者和企业实现业务流程的自动化。它支持 BPMN 2.0 标准&#xff0c;适用于各种规模的企业和项目。Flowable 的核心功能包括流程定义、流程执行、任…

网络安全-openssl工具

OpenSSl是一个开源项目&#xff0c;包括密码库和SSL/TLS工具集。它已是在安全领域的事实标准&#xff0c;并且拥有比较长的历史&#xff0c;现在几乎所有的服务器软件和很多客户端都在使用openssl&#xff0c;其中基于命令行的工具是进行加密、证书管理以及测试最常用到的软件。…

【Web开发】PythonAnyWhere免费部署Django项目

PythonAnyWhere免费部署Django项目 文章目录 PythonAnyWhere免费部署Django项目将项目上传到GitHub从GitHub下载Django项目创建Web应用配置静态文件将项目上传到GitHub 打开项目,输入以下命令,生成Django项目依赖包。pip list --format=freeze > requirements.txt打开Git …

视频的分片上传

分片上传需求分析&#xff1a; 项目中很多地方需要上传视频&#xff0c;如果视频很大&#xff0c;上传到服务器需要很多时间 &#xff0c;这个时候体验就会很差。所以需要前端实现分片上传的功能。 要实现分片上传&#xff0c;需要对视频进行分割&#xff0c;分割成不同的大小…

Moonshot AI 新突破:MoBA 为大语言模型长文本处理提效论文速读

前言 在自然语言处理领域&#xff0c;随着大语言模型&#xff08;LLMs&#xff09;不断拓展其阅读、理解和生成文本的能力&#xff0c;如何高效处理长文本成为一项关键挑战。近日&#xff0c;Moonshot AI Research 联合清华大学、浙江大学的研究人员提出了一种创新方法 —— 混…

Deepseek首页实现 HTML

人工智能与未来&#xff1a;机遇与挑战 引言 在过去的几十年里&#xff0c;人工智能&#xff08;AI&#xff09;技术取得了突飞猛进的发展。从语音助手到自动驾驶汽车&#xff0c;AI 正在深刻地改变我们的生活方式、工作方式以及社会结构。然而&#xff0c;随着 AI 技术的普及…

VS2022配置FFMPEG库基础教程

1 简介 1.1 起源与发展历程 FFmpeg诞生于2000年&#xff0c;由法国工程师Fabrice Bellard主导开发&#xff0c;其名称源自"Fast Forward MPEG"&#xff0c;初期定位为多媒体编解码工具。2004年后由Michael Niedermayer接任维护&#xff0c;逐步发展成为包含音视频采…

kafka基本知识

什么是 Kafka&#xff1f; Apache Kafka 是一个开源的分布式流处理平台&#xff0c;最初由 LinkedIn 开发&#xff0c;后来成为 Apache 软件基金会的一部分。Kafka 主要用于构建实时数据管道和流处理应用程序。它能够高效地处理大量的数据流&#xff0c;广泛应用于日志收集、数…

类型系统下的语言分类与类型系统基础

类型系统是一种根据计算值的种类对程序语法进行分类的方式&#xff0c;目的是自动检查是否有可能导致错误的行为。 —Benjamin.C.Pierce&#xff0c;《类型与编程语言》&#xff08;2002&#xff09; 每当谈到编程语言时&#xff0c;人们常常会提到“静态类型”和“动态类型”。…

有没有使用wxpython开发的类似于visio或drawio的开源项目(AI生成)

有没有使用wxpython开发的类似于visio或drawio的开源项目 是的&#xff0c;有一些使用wxPython开发的类似于Microsoft Visio或draw.io&#xff08;现为diagrams.net&#xff09;的开源项目。wxPython 是一个跨平台的GUI工具包&#xff0c;它允许Python开发者创建桌面应用程序&…

【MySQL 一 数据库基础】深入解析 MySQL 的索引(3)

索引 索引操作 自动创建 当我们为一张表加主键约束(Primary key)&#xff0c;外键约束(Foreign Key)&#xff0c;唯一约束(Unique)时&#xff0c;MySQL会为对应的的列自动创建一个索引&#xff1b;如果表不指定任何约束时&#xff0c;MySQL会自动为每一列生成一个索引并用ROW_I…

【C++】优先级队列宝藏岛

> &#x1f343; 本系列为初阶C的内容&#xff0c;如果感兴趣&#xff0c;欢迎订阅&#x1f6a9; > &#x1f38a;个人主页:[小编的个人主页])小编的个人主页 > &#x1f380; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 > ✌️ &#x1f91e; &#x1…

List 接口中的 sort 和 forEach 方法

List 接口中的 sort 和 forEach 方法是 Java 8 引入的两个非常实用的函数&#xff0c;分别用于 排序 和 遍历 列表中的元素。以下是它们的详细介绍和用法&#xff1a; sort 函数 功能 对列表中的元素进行排序。 默认使用自然顺序&#xff08;如数字从小到大&#xff0c;字符…

MusicGPT的本地化部署与远程调用:让你的Windows电脑成为AI音乐工作站

文章目录 前言1. 本地部署2. 使用方法介绍3. 内网穿透工具下载安装4. 配置公网地址5. 配置固定公网地址 前言 在如今快节奏的生活里&#xff0c;音乐不仅能够抚慰我们的心灵&#xff0c;还能激发无限创意。想象一下&#xff0c;在忙碌的工作间隙或闲暇时光中&#xff0c;只需输…

Unity通过Vosk实现离线语音识别方法

标注&#xff1a;deepseek直接生成&#xff0c;待验证 在Unity中实现离线语音识别可以通过集成第三方语音识别库来实现。以下是一个使用 Unity 和 Vosk&#xff08;一个开源的离线语音识别库&#xff09;的简单示例。 准备工作 Vosk&#xff1a;一个开源的离线语音识别库&am…

智能优化算法:莲花算法(Lotus flower algorithm,LFA)介绍,提供MATLAB代码

一、 莲花算法 1.1 算法原理 莲花算法&#xff08;Lotus flower algorithm&#xff0c;LFA&#xff09;是一种受自然启发的优化算法&#xff0c;其灵感来源于莲花的自清洁特性和授粉过程。莲花的自清洁特性&#xff0c;即所谓的“莲花效应”&#xff0c;是由其叶片表面的微纳…

企业数据集成:实现高效调拨出库自动化

调拨出库对接调出单-v&#xff1a;旺店通企业奇门数据集成到用友BIP 在企业信息化管理中&#xff0c;数据的高效流转和准确对接是实现业务流程自动化的关键。本文将分享一个实际案例&#xff0c;展示如何通过轻易云数据集成平台&#xff0c;将旺店通企业奇门的数据无缝集成到用…

数据库管理-第295期 IT架构与爆炸半径(20250221)

数据库管理295期 2025-02-21 数据库管理-第295期 架构与爆炸半径&#xff08;20250221&#xff09;1 术语新解2 硬件&#xff1a;存储VS本地盘3 数据库3.1 多模VS专用3.2 集中式VS分布式 4 公有云VS非公有云总结 数据库管理-第295期 架构与爆炸半径&#xff08;20250221&#x…

基于WOA鲸鱼优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a/matlab2024b 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频…