当前位置: 首页 > article >正文

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

嘿各位前端界的“码农”们以及那些自认为“码农”但实际上只是“复制粘贴侠”的朋友们大家好今天我们不聊那些花里胡哨的 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给他表演一个“原地起飞”。祝大家编码愉快头发浓密

相关文章:

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

嘿,各位前端界的“码农”们,以及那些自认为“码农”但实际上只是“复制粘贴侠”的朋友们,大家好!今天我们不聊那些花里胡哨的 CSS 动画,也不聊那些让你头发掉光的 TypeScript 泛型。今天,我们要聊聊一个稍微…...

别再死记硬背了!用Python的NumPy库实战CR、LU、QR分解,5分钟搞懂矩阵分解到底在干啥

用Python实战矩阵分解:CR、LU、QR的代码实现与可视化解析 线性代数中的矩阵分解就像化学中的元素周期表——它揭示了复杂结构背后的基本组成单元。对于工程师和数据科学家来说,掌握矩阵分解不仅是为了通过考试,更是为了在实际项目中高效解决线…...

Shopee一面:你使用 RAG 给大模型一个输入,系统是怎样的工作流程?

👔面试官:当你给 RAG 系统输入一个问题,整个系统的工作流程是怎样的?从用户提问到最终拿到答案,中间经历了哪些步骤? 🙋‍♂️我:RAG 就是检索加生成嘛,用户提问之后去数…...

Cy5-Fe₃O₄ NPs,Cy5标记四氧化三铁纳米颗粒,反应步骤

Cy5-Fe₃O₄ NPs,Cy5标记四氧化三铁纳米颗粒,反应步骤Cy5-Fe₃O₄ NPs(Cy5标记四氧化三铁纳米颗粒)通常通过“磁性纳米核构建—表面功能化—荧光染料偶联—纯化与表征”几个关键步骤完成,整体反应路径强调界面化学的可…...

BilibiliDown:5分钟快速上手,高效下载B站视频的终极方案

BilibiliDown:5分钟快速上手,高效下载B站视频的终极方案 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com…...

多智能体推理与协作的薄环节优化

摘要基于大语言模型的多智能体框架通过多角色协作来解决复杂的推理任务。然而,现有方法往往存在推理不稳定的问题:单个智能体的错误在协作过程中被放大,从而损害整体性能。当前研究主要侧重于增强高能力智能体或抑制不可靠的输出以提升框架有…...

魔兽世界:私服盗贼爆发连招与单体输出循环教学

在《魔兽世界》这款经典的MMORPG游戏中,盗贼职业一直以其高机动性和爆发输出著称。特别是在魔兽世界私服环境中,玩家可以通过自定义服务器规则来优化角色构建,体验更纯粹的PVE内容。本文将从职业特性、技能机制、装备选择、副本应用等多维度&…...

Java Loom响应式改造必踩的5个安全雷区:从Project Loom Beta到生产级落地的零信任实践

第一章:Java Loom响应式改造必踩的5个安全雷区:从Project Loom Beta到生产级落地的零信任实践线程局部变量(ThreadLocal)在虚拟线程中的隐式泄漏 Project Loom 的虚拟线程复用机制会导致 ThreadLocal 实例跨请求残留。若未显式清理…...

Cherry Studio下载安装与小白使用教程:Windows电脑轻松上手AI助手

Cherry Studio下载安装与小白使用教程:Windows电脑轻松上手AI助手 作为一名每天都要处理大量文字和代码的打工人,最近我一直在寻找一个能集成各种大模型的桌面端工具。毕竟网页版切来切去真的很麻烦。试了一圈,最后我被 Cherry Studio 给安利…...

2025届学术党必备的六大降AI率方案推荐榜单

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 要想有效地把文本的AIGC检测率降下来,就得从词汇、句式以及逻辑结构这三个方面着…...

2025届学术党必备的六大降AI率方案实测分析

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 基于自然语言处理跟深度学习算法构建了AI论文查重系统,它会对文本语义展开细致分…...

STM32F103驱动维特智能JY61P六轴传感器:从USB-TTL调试到按键唤醒的完整避坑指南

STM32F103驱动维特智能JY61P六轴传感器:从硬件调试到数据解析的全流程实战 在嵌入式开发领域,姿态传感器正逐渐成为各类智能设备的标配组件。维特智能JY61P作为一款性价比较高的六轴姿态传感器,集成了三轴加速度计和三轴陀螺仪,能…...

快速体验CAM++:上传两段语音,秒级判断是否同一说话人

快速体验CAM:上传两段语音,秒级判断是否同一说话人 1. 引言:从“听声辨人”到一键验证 你有没有想过,只凭一段语音,就能在茫茫人海中确认一个人的身份?这听起来像是科幻电影里的情节,但今天&a…...

Claude Opus 4.7 API 接入指南:最强模型实测与中转配置教程(2026)

上周 Anthropic 放出了 Claude Opus 4.7 的 API 权限,我第一时间冲进去测了。复杂推理和长上下文代码生成这两块,确实把我之前用的 Claude 4.6 按在地上摩擦。Claude Opus 4.7 是 Anthropic 2026 年发布的旗舰推理模型,接入方式兼容 OpenAI S…...

DAMO-YOLO入门指南:理解COCO 80类标准与达摩院扩展类别的映射关系

DAMO-YOLO入门指南:理解COCO 80类标准与达摩院扩展类别的映射关系 你是不是刚接触DAMO-YOLO,看着它强大的目标检测能力很兴奋,但一看到“COCO 80类”和“达摩院扩展类别”这些术语就有点懵?别担心,这种感觉我刚开始也…...

Codex + 自建中转站,用不完的token+GPT5.4 做成了一个AI机器人

Codex 自建中转站,用不完的tokenGPT5.4 做成了一个AI机器人 最近因为gemini实在太贵,订阅了两个月后还是和团队一起搞了自建中转站,这也正是高龄程序员的痛,所以也想着给自己多搞个退路,对于AI,我的第一感…...

白宫拟开放Claude漏洞挖掘AI,军方禁令与民用部署冲突激化

美国政府正计划授权主要联邦机构使用Anthropic公司Claude Mythos模型的修改版本。该AI模型能够快速识别网络安全漏洞并具备漏洞利用能力,引发了广泛关注。据彭博社援引内部备忘录报道,白宫管理与预算办公室(OMB)联邦首席信息官Gre…...

推荐系统实时更新策略

推荐系统实时更新策略:让内容推荐更懂你 在信息爆炸的时代,推荐系统已成为用户获取内容的核心工具。传统的推荐模型往往依赖离线训练,难以捕捉用户兴趣的实时变化。实时更新策略通过动态调整推荐结果,让系统更敏捷地响应用户行为…...

警惕AI全自动攻击!Claude Opus成功构建Chrome漏洞武器化链路

在 Anthropic 公司发布 Mythos 和 Project Glasswing 模型引发激烈争论之际,一位安全研究人员展示了前沿 AI 技术对网络安全的实际影响。该研究突破了理论警告的局限,成功利用 Claude Opus 构建出针对 Google Chrome 复杂 V8 JavaScript 引擎的完整漏洞利…...

算法训练营第八天|88.合并两个有序数组

题目链接:https://leetcode.cn/problems/merge-sorted-array/ 视频链接:https://www.bilibili.com/video/BV1Gr16B2EGf/状态:做出来了思路:双指针法:我们为两个数组分别设置一个指针 p1​ 与 p2​ 来作为队列的头部指针…...

攻击者可利用的 FortiSandbox 漏洞 PoC 公开,可执行任意命令

网络安全研究人员已公开披露针对 Fortinet 旗下 FortiSandbox 产品高危漏洞(CVE-2026-39808)的概念验证(PoC)利用代码。该漏洞允许未经身份验证的攻击者以 root 最高权限执行任意操作系统命令,且无需任何登录凭证。 该…...

从航拍到模型:手把手教你用‘焦距’和‘像元尺寸’反算无人机航高(附Excel计算工具)

从航测参数到飞行方案:无人机航高计算的工程实践指南 当大疆M300RTK搭载P1全画幅相机盘旋在工地上空时,机载计算机显示的实时航高数字背后,隐藏着一套精密的计算逻辑。对于航测工程师而言,掌握从相机参数到飞行参数的转换能力&…...

**构建去中心化金融新范式:基于Solidity的DeFi协议开发实战解析**在区块链技术飞速发展的今天,**

构建去中心化金融新范式:基于Solidity的DeFi协议开发实战解析 在区块链技术飞速发展的今天,DeFi(去中心化金融) 已成为推动Web3生态落地的核心引擎之一。它通过智能合约实现了无需中介的信任机制,极大提升了资产流动性…...

**点云处理新范式:基于Python的高效三维数据滤波与分割实战**在自动驾

点云处理新范式:基于Python的高效三维数据滤波与分割实战 在自动驾驶、机器人导航和工业质检等前沿领域,点云数据已成为关键输入信息。它由成千上万甚至百万级的三维坐标(x, y, z)组成,常来自激光雷达(LiD…...

当‘事实’遇见代码:用Python爬虫与NLP,亲手验证新闻中的‘莫斯科街道’悖论

当‘事实’遇见代码:用Python爬虫与NLP,亲手验证新闻中的‘莫斯科街道’悖论 在信息爆炸的时代,我们每天被无数新闻包围,但你是否想过,这些所谓的"事实"究竟是如何被构建的?1980年代,…...

Ubuntu 18.04 ROS安装遇坑记:手把手教你修复‘EXPKEYSIG’签名无效错误

Ubuntu 18.04 ROS安装遇坑记:手把手教你修复‘EXPKEYSIG’签名无效错误 第一次在Ubuntu上安装ROS时,那种兴奋感很快被终端里鲜红的错误提示浇灭——EXPKEYSIG F42ED6FBAB17C654。作为机器人开发的基础环境,ROS的安装本应是入门第一步&#xf…...

G-Helper终极指南:解锁华硕ROG笔记本隐藏性能的黑科技神器

G-Helper终极指南:解锁华硕ROG笔记本隐藏性能的黑科技神器 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix…...

【X-STILT模型第一期】X-STILT 模型概述

目录X-STILT 模型概述支持的观测平台与气体物种GitHub 仓库中的内置核心脚本/功能X-STILT 模型的下载安装一、 下载与安装模型 (Download and install model)二、 前置条件与数据准备 (Prerequisites)1. 依赖卫星观测的柱浓度模拟 (For SATELLITE-dependent column simulation)…...

在国产化ARM平台(如鲲鹏)上,用Eclipse搞定JavaFX开发的避坑指南

在国产化ARM平台(如鲲鹏)上构建JavaFX开发环境的全流程指南 当国产化替代浪潮遇上ARM架构的崛起,开发者们正面临一个全新的技术挑战:如何在华为鲲鹏等国产ARM服务器上搭建高效的JavaFX开发环境?与传统的x86平台不同&am…...

【论文学习】利用卫星观测数据的 X-STILT 模型详解

目录 J2018-提出 X-STILT (v1)模型( C O 2 CO_2 CO2​总量反演) 2. 核心研究方法:X-STILT 模型 3. 使用的数据资源 4. 案例研究:沙特阿拉伯利雅得 J2022-改进 X-STILT 模型( C O 2 CO_2 CO2​部门归因) 1. 研究核心:利用 C O 2 CO_2 CO2​ 与 C O CO CO 的排放比例 2.…...