React 多标签页同步:利用 SharedWorker 在多个 React 实例间共享持久化 WebSocket 连接

news2026/4/29 15:33:55
嘿各位前端界的“码农”们以及那些自认为“码农”但实际上只是“复制粘贴侠”的朋友们大家好今天我们不聊那些花里胡哨的 CSS 动画也不聊那些让你头发掉光的 TypeScript 泛型。今天我们要聊聊一个稍微有点“硬核”但一旦用上了就会让你感觉“这代码写得真香”的话题——如何在多个 React 标签页之间共享一个 WebSocket 连接。想象一下你的产品经理PM是个急性子他希望用户打开 10 个标签页这 10 个标签页都能实时收到同一个通知而且服务器端的连接数只有 1 个。如果你还在每个useEffect里都new WebSocket(...)那不好意思服务器端早就因为 TCP 连接数超限而把你拉黑了就像你去餐厅吃饭一个人点了 10 份菜单服务员服务器当场给你掀桌子。今天我们要请出一位“幕后英雄”——SharedWorker。它就像是一个住在浏览器后台的“隐形管家”专门负责替你管着那个昂贵的 WebSocket 连接然后像个广播站一样把消息分发给你打开的所有标签页。准备好了吗我们要开始“造轮子”了但这轮子可是能省下你服务器一大笔钱的第一部分WebSocket 的“单线程”诅咒在深入 SharedWorker 之前我们得先搞清楚为什么现在的方案是个坑。假设你写了一个简单的 React 组件用来连接一个 WebSocket 服务// ❌ 错误示范每个标签页一个连接 const ChatComponent () { const [messages, setMessages] useState([]); useEffect(() { const socket new WebSocket(ws://api.example.com/chat); socket.onmessage (event) { const newMsg JSON.parse(event.data); setMessages(prev [...prev, newMsg]); }; // 连接成功 console.log(Connection established); return () { socket.close(); }; }, []); // 注意依赖项是空数组但这只是个假象 };当你打开这个组件的 10 个标签页时实际上发生了什么浏览器为每个标签页创建了一个独立的 JavaScript 执行环境。每个环境都执行了useEffect。啪你向服务器发出了 10 个 TCP 握手请求。服务器“哇这家伙开了 10 个房间是不是来开 party 的”如果你在开发环境热重载HMR还会让你更崩溃。你改了一行代码页面刷新了一个 WebSocket 连接断开又建立了一个。服务器端的日志就像瀑布一样刷屏。而且当你收到消息时你需要在 10 个标签页里分别调用setState。如果消息来了只有标签页 A 在前台标签页 B 和 C 里的数据更新了但用户看不见这叫什么这叫“无效渲染”浪费 CPU 和电池。所以我们需要一个“中央处理器”它要负责唯一性全站只开一个 WebSocket 连接。广播性消息来了它要通知所有标签页。持久性即使你关闭了标签页连接不能断除非你真的关了浏览器。SharedWorker 就是这个中央处理器。第二部分SharedWorker 是个什么鬼SharedWorker顾名思义就是一个可以被多个浏览器上下文包括不同的标签页、iframe 甚至 worker共享的 Worker。它最大的特点就是它运行在独立的线程里而且这个线程在所有标签页之间是共享的。这就像是你在公司里有一个专门的“接线员”不管你坐在哪个工位标签页接线员都在那里。你不用每个工位都配一个接线员只要告诉接线员“我有事找你”他就把电话接过去。但是SharedWorker 有一个极其坑爹的限制同源策略。这意味着你的 SharedWorker 脚本必须托管在一个独立的 URL 下而且所有连接它的页面必须来自同一个域或协议/端口相同。如果你在localhost:3000运行 React你的 Worker 脚本通常需要放在public/目录下或者通过特殊的构建工具如 Vite 的插件处理。第三部分架构设计——谁来管连接这是最关键的一步。我们要明确职责分工。方案 A糟糕React 组件里创建 SharedWorker - React 组件管理 WebSocket 状态。结果React 组件需要处理断线重连、心跳包、状态同步逻辑。React 本来就擅长 UI 渲染把它搞得像个网络库这叫“职责不清”就像让厨师去修水管一样。方案 B正确SharedWorker唯一的 WebSocket 管理者。它负责连接、发送、接收、断线重连。它不关心谁在用只负责把数据广播出去。React 组件纯粹的消费者。它通过BroadcastChannel与 SharedWorker 通信或者直接监听 SharedWorker 的广播。数据流向React A (Tab 1) - BroadcastChannel(“worker_channel”) - SharedWorker - WebSocket - ServerSharedWorker - WebSocket Data - ServerSharedWorker - BroadcastChannel(“worker_channel”) - React A (Tab 1)SharedWorker - BroadcastChannel(“worker_channel”) - React B (Tab 2)…注意这里用到了BroadcastChannel。SharedWorker 虽然能和所有标签页通信但它不像 Service Worker 那样能直接监听全局事件。SharedWorker 需要一个“中介”来广播消息给所有标签页。BroadcastChannelAPI 就是这个完美的中介。第四部分SharedWorker 端代码实现首先我们需要创建一个独立的 JS 文件我们就叫它shared-worker.js。这个文件放在你的 React 项目的public目录下这样你可以直接通过 URL 访问它。// public/shared-worker.js class WebSocketManager { constructor() { this.ws null; this.reconnectAttempts 0; this.maxReconnectAttempts 10; this.reconnectDelay 1000; this.listeners new Set(); // 保存所有订阅者的回调 this.connected false; // 这里的 URL 需要替换成你真实的 WebSocket 地址 this.wsUrl ws://your-api-server.com/ws; this.connect(); } connect() { console.log([SharedWorker] Attempting to connect to WebSocket...); this.ws new WebSocket(this.wsUrl); this.ws.onopen () { console.log([SharedWorker] WebSocket Connected!); this.connected true; this.reconnectAttempts 0; // 重置重连计数 // 连接成功后通知所有标签页当前状态 this.broadcast({ type: WS_STATUS, payload: { status: connected } }); }; this.ws.onmessage (event) { console.log([SharedWorker] Received data from Server:, event.data); // 收到服务器数据广播给所有 React 标签页 this.broadcast({ type: WS_MESSAGE, payload: event.data }); }; this.ws.onclose (event) { console.log([SharedWorker] WebSocket Closed. Code:, event.code); this.connected false; this.broadcast({ type: WS_STATUS, payload: { status: disconnected, code: event.code } }); this.scheduleReconnect(); }; this.ws.onerror (error) { console.error([SharedWorker] WebSocket Error:, error); }; } scheduleReconnect() { if (this.reconnectAttempts this.maxReconnectAttempts) { this.reconnectAttempts; const delay this.reconnectDelay * this.reconnectAttempts; // 指数退避 console.log([SharedWorker] Reconnecting in ${delay}ms... (Attempt ${this.reconnectAttempts})); setTimeout(() { this.connect(); }, delay); } else { console.error([SharedWorker] Max reconnection attempts reached. Giving up.); this.broadcast({ type: WS_STATUS, payload: { status: error } }); } } // 广播消息给所有连接的标签页 broadcast(message) { // 我们这里使用 BroadcastChannel API 来广播 // 注意SharedWorker 没有全局的 broadcastChannel 实例 // 但我们可以利用 Worker 端的 postMessage 发送给所有 port // 不过为了让 React 端简单我们通常让 SharedWorker 启动一个 BroadcastChannel // 或者更简单的方法是SharedWorker 作为一个“代理”它接收消息然后广播。 // 但这里我们主要处理 WebSocket 到 React 的流向。 // 实际上SharedWorker 内部也可以直接使用 BroadcastChannel因为它也是 JS 环境 if (this.channel) { this.channel.postMessage(message); } } // React 标签页发消息给 SharedWorker例如发送聊天内容 send(data) { if (this.connected this.ws.readyState WebSocket.OPEN) { this.ws.send(JSON.stringify(data)); } else { console.warn([SharedWorker] Cannot send: Not connected.); } } } // 初始化 SharedWorker 逻辑 // 注意SharedWorker 是单例的无论你打开多少个标签页这里只会运行一次 const manager new WebSocketManager(); // 监听来自标签页的消息 self.onconnect (event) { const port event.ports[0]; // 建立端口通信 port.start(); // 初始化 BroadcastChannel 用于接收 SharedWorker 自己广播的消息 manager.channel new BroadcastChannel(react-shared-worker-channel); manager.channel.onmessage (event) { // 将消息转发给对应的标签页 port.postMessage(event.data); }; // 监听标签页发来的消息例如发送文本 port.onmessage (event) { const { type, payload } event.data; if (type SEND_MESSAGE) { manager.send(payload); } }; // 欢迎标签页连接 port.postMessage({ type: HELLO, payload: Connection established with SharedWorker }); };看懂了吗这段代码里class WebSocketManager是核心。它持有 WebSocket 实例。onconnect事件确保了无论你打开多少个标签页SharedWorker 都会为每个标签页创建一个port这样它们就能互相通信了。关键点我们在 SharedWorker 里也用了一个BroadcastChannel。为什么因为 SharedWorker 需要把自己收到的服务器数据广播给所有监听它的 React 标签页。这个BroadcastChannel的名字叫react-shared-worker-channel这是我们在两个地方SharedWorker 和 React约定的“暗号”。第五部分React 端代码实现——Hook 化封装现在我们怎么在 React 里用呢我们不能在组件里直接new SharedWorker因为这样每个组件实例都会创建一个新的 Worker那就没意义了。我们需要一个全局的 Worker 实例。这里我们使用useRef来存储 Worker 实例确保全局唯一。// utils/useSharedWorker.js import { useEffect, useRef, useState, useCallback } from react; export const useSharedWorker (workerUrl) { const [status, setStatus] useState(disconnected); // connected, disconnected, error const [messages, setMessages] useState([]); // 使用 ref 存储 worker 和 channel避免在 render 中读取导致无限循环 const workerRef useRef(null); const channelRef useRef(null); const messagesRef useRef(messages); // 保持最新的消息引用 // 更新消息引用避免闭包陷阱 useEffect(() { messagesRef.current messages; }, [messages]); useEffect(() { if (typeof window undefined) return; console.log([React] Initializing SharedWorker...); try { // 1. 创建 SharedWorker const worker new SharedWorker(workerUrl, { type: module }); workerRef.current worker; // 2. 创建 BroadcastChannel 用于接收 SharedWorker 的广播 const channel new BroadcastChannel(react-shared-worker-channel); channelRef.current channel; // 3. 监听 SharedWorker 发来的消息 channel.onmessage (event) { const { type, payload } event.data; console.log([React] Received from SharedWorker:, event.data); switch (type) { case HELLO: setStatus(connected); break; case WS_STATUS: setStatus(payload.status); break; case WS_MESSAGE: // 收到 WebSocket 数据 setMessages(prev [...prev, payload]); break; default: console.warn([React] Unknown message type:, type); } }; // 4. 发送消息给 SharedWorker const sendMessage useCallback((data) { if (workerRef.current workerRef.current.port) { workerRef.current.port.postMessage({ type: SEND_MESSAGE, payload: data }); } }, []); // 5. 处理 Worker 端的错误可选比较复杂暂略 return () { console.log([React] Cleaning up SharedWorker connection...); channel.close(); if (workerRef.current) { workerRef.current.port.close(); } }; } catch (error) { console.error([React] Failed to initialize SharedWorker:, error); setStatus(error); } }, [workerUrl]); return { status, messages, sendMessage, }; };这个 Hook 做了什么Singleton Patternnew SharedWorker只会执行一次。因为useEffect的依赖项是[workerUrl]只要 URL 不变Worker 就不会重复创建。State Management它管理了连接状态connected/disconnected和消息列表。Message Passing它通过BroadcastChannel接收来自 SharedWorker 的数据并更新 React State。第六部分实战应用——构建一个聊天室让我们把上面的代码组合起来写一个简单的聊天室组件。为了演示效果我们在 SharedWorker 里模拟一个服务器发送消息的循环。1. 修改public/shared-worker.js我们在onmessage里加一点模拟逻辑让它每隔几秒向所有标签页广播一条消息。// public/shared-worker.js (修改版) // ... (前面的 WebSocketManager 类代码保持不变) ... // 模拟服务器推送消息 setInterval(() { if (manager.connected) { const mockServerMsg { id: Date.now(), text: 这是来自 SharedWorker 的广播消息当前时间 ${new Date().toLocaleTimeString()}, from: System }; manager.broadcast({ type: WS_MESSAGE, payload: mockServerMsg }); } }, 5000); // 每5秒广播一次2. React 组件// App.js import React from react; import { useSharedWorker } from ./utils/useSharedWorker; const App () { const { status, messages, sendMessage } useSharedWorker(/shared-worker.js); const handleSend () { const text prompt(请输入你想说的话仅演示用); if (text) { sendMessage({ type: chat, text }); } }; return ( div style{{ padding: 20px, fontFamily: sans-serif }} h1React SharedWorker 聊天室/h1 div style{{ marginBottom: 20px }} strong连接状态/strong span style{{ color: status connected ? green : red, marginLeft: 10px }} {status.toUpperCase()} /span /div div style{{ border: 1px solid #ccc, padding: 10px, height: 300px, overflowY: auto }} {messages.length 0 p暂无消息.../p} {messages.map((msg, index) ( div key{msg.id || index} style{{ marginBottom: 8px }} span style{{ fontWeight: bold, color: blue }} {msg.from || Unknown}: /span span{msg.text}/span /div ))} /div button onClick{handleSend} disabled{status ! connected} style{{ marginTop: 10px }} 发送消息 (测试 SharedWorker) /button p style{{ fontSize: 12px, color: #666, marginTop: 20px }} * 提示请打开多个标签页你会发现它们都能收到上面的广播消息且只有一个 WebSocket 连接。 /p /div ); }; export default App;第七部分那些“坑”与“痛”写到这里你以为这就完事了天真现实总是比代码复杂得多。作为资深专家我必须告诉你在生产环境中使用 SharedWorker 会遇到什么鬼问题。1. 热重载HMR的噩梦在开发环境下当你修改代码保存时Vite 或 Webpack 会把旧的模块替换掉。如果旧的模块里有个 SharedWorker它会尝试关闭它。但问题是SharedWorker 是全局单例旧的 Worker 可能还在后台运行新的 Worker 也启动了。结果就是你会有两个 WebSocket 连接在后台打架或者端口占用。解决方案你需要监听window.addEventListener(beforeunload, ...)来确保 Worker 优雅关闭。更高级的做法是使用 Vite 插件在开发时禁用 SharedWorker 的自动重载或者让 Worker 容忍多次连接。2. 跨域与同源策略SharedWorker 必须在一个独立的文件路径下。如果你的 React 应用是 SPA单页应用你可能在开发时用http://localhost:3000但 SharedWorker 脚本在http://localhost:3000/shared-worker.js。这没问题。但是如果你的 WebSocket 服务器和前端服务器不是同一个域SharedWorker 的 CORS 配置会非常麻烦。SharedWorker 发起的 WebSocket 请求它的 Origin 是null如果是本地文件或者是你的 SharedWorker 脚本的 URL。如果你的 WebSocket 服务器只允许前端域名的请求SharedWorker 可能会被拦截。解决方案确保 WebSocket 服务器配置了正确的 CORS 头或者使用 Nginx 反向代理来统一域名。3. 内存泄漏如果你在useEffect的清理函数里没有正确关闭BroadcastChannel和worker.port当你卸载组件时SharedWorker 端的监听器可能没有被移除。虽然 SharedWorker 生命周期很长但如果组件卸载了还在监听这就像是一个僵尸在后台吃内存。4. 序列化限制SharedWorker 和 React 组件之间的通信是通过postMessage传递对象。这依赖于structuredClone算法。这意味着你不能直接传递函数、DOM 节点或者一些特殊的对象如Error对象的部分属性。如果你传递了一个包含循环引用的对象SharedWorker 会报错。解决方案在发送前务必对数据进行深拷贝和清洗只保留 JSON 可序列化的数据。第八部分高级优化——不仅仅是广播现在我们实现了“广播”。但如果我想实现“点对点”聊天呢比如标签页 A 发消息只有标签页 B 能收到SharedWorker 其实可以维护一个“用户 ID 到 Port”的映射表。修改shared-worker.js// 在 SharedWorker 类中添加 this.clients new Map(); // 存储 { clientId: port } // 修改 onconnect self.onconnect (event) { const port event.ports[0]; const clientId client_${Date.now()}_${Math.random()}; port.start(); this.clients.set(clientId, port); // 广播当前在线用户列表 this.broadcast({ type: USER_LIST, payload: Array.from(this.clients.keys()) }); // 监听私聊消息 port.onmessage (event) { const { type, payload } event.data; if (type SEND_MESSAGE) { // 如果消息里有 targetClientId只发给那个人 if (payload.targetClientId) { const targetPort this.clients.get(payload.targetClientId); if (targetPort) { targetPort.postMessage({ type: WS_MESSAGE, payload: payload }); } } else { // 否则广播 this.broadcast({ type: WS_MESSAGE, payload: payload }); } } }; port.onclose () { this.clients.delete(clientId); this.broadcast({ type: USER_LIST, payload: Array.from(this.clients.keys()) }); }; };这样SharedWorker 就变成了一个真正的消息代理服务器。你甚至可以把它扩展成支持房间Room的概念。第九部分性能与并发有人会问SharedWorker 是单线程的如果我在 SharedWorker 里处理了大量的 WebSocket 消息会不会卡死 UI虽然 SharedWorker 不影响 UI但会影响消息处理速度是的SharedWorker 是单线程的。如果每秒有 1000 条消息涌入SharedWorker 必须一条一条处理。解决方案节流与防抖在 SharedWorker 里对高频消息进行聚合。比如如果 100ms 内收到了 10 条消息不要广播 10 次而是打包成 1 次广播。Worker Pool如果业务极其复杂SharedWorker 可能不够用了。这时候你可能需要引入更底层的技术比如使用 Node.js 写一个真正的后端服务来转发 WebSocket或者使用Service Worker结合Cache API但这比较复杂因为 Service Worker 不能直接建立 WebSocket 连接。但对于绝大多数前端应用如聊天、实时报表、状态同步SharedWorker 的性能是绰绰有余的。第十部分总结与展望好了老铁们今天的“讲座”就到这里。我们回顾一下今天做了什么痛点多标签页开多个 WebSocket 连接导致资源浪费和状态不同步。方案利用 SharedWorker 作为“中央处理器”管理连接利用 BroadcastChannel 作为“广播电台”分发消息。代码我们写了完整的 Worker 逻辑、React Hook 封装以及一个简单的聊天室 Demo。避坑我们讨论了热重载、同源策略和内存泄漏。使用 SharedWorker 的好处是显而易见的服务器压力骤降你的服务器不再需要为每个标签页维护一个 TCP 连接。状态同步在一个标签页的操作能实时反映到所有标签页。离线能力部分虽然 SharedWorker 不会自动缓存页面但它能更好地控制网络资源的生命周期。但是技术这东西有利就有弊。SharedWorker 的调试比普通 JS 难得多你很难在 Chrome DevTools 里直接打断点看到 SharedWorker 的变量通常只能看 console而且它增加了架构的复杂度。什么时候该用什么时候不该用该用即时通讯、实时协作工具、复杂的仪表盘、需要跨标签页状态同步的 Web 应用。不该用普通的博客、静态展示页、简单的表单提交。为了用 SharedWorker 而用 SharedWorker那是典型的“为了炫技而炫技”最后只会让维护你代码的人也就是你自己在半夜三点痛哭流涕。最后记住一句话SharedWorker 是浏览器提供的幕后英雄它让 Web 应用从“一个个孤岛”变成了“一个整体”。希望这篇文章能帮你搞定那个让你抓耳挠腮的多标签页同步问题。下次遇到 PM 说“我要所有标签页都显示同一个进度条”的时候别慌拿出你的 SharedWorker给他表演一个“原地起飞”。祝大家编码愉快头发浓密

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…