Node.js WebSocket长连接实战:心跳保活与断线重连源码解析
简介一份面向WebSocket初学者的客户端与服务端实例源码包由Java实现服务端客户端基于HTML5 WebSocket。WebSocket可建立客户端与服务端之间的全双工长连接这份实例展示了这一机制。资源支持客户端测试任意语言服务端也可用服务端测试任意语言客户端便于理解握手、消息收发及跨语言联动。运行环境要求服务端JDK7以上客户端Tomcat7以上。压缩包共16个文件主要包含Java源码、JSP页面、class文件和Eclipse工程配置.project、.classpath、.settings等源码与配置分离可直接导入IDE运行。包内同时提供客户端与服务端两个工程模块目录划分清晰便于区分对照。整体仅16KB结构精简适合快速搭建测试环境或作为WebSocket入门模板。目前已有1264人学习下载适合学习Java WebSocket、HTML5实时通信或需验证多语言服务端兼容性的开发者。通过该实例可掌握从客户端到服务端的完整调用链路并以此为基础扩展聊天室、消息推送等实时应用同时也可借助跨语言测试特性排查不同语言实现下的连接异常问题。1. webSocket实例源码从零搭一套长连接通信不只是跑通 demo如果你写过多端应用大概率经历过这样的场景服务端算完一批数据客户端这边却只能靠轮询一遍遍去问“好了吗”问一次两次还行一秒问十次服务器和带宽都得跟着遭殃。这个 webSocket 客户端与服务端实例源码就是用来解决“服务端主动找客户端说话”这个问题的。它里面有一套完整的 Node.js 服务端实现、一个可直接使用的客户端封装以及基于原生 WebSocket 协议的消息收发示例不是只演示“连接成功”的那种教学 demo而是把连接管理、心跳保活、断线重连、消息广播这些生产环境里真正绕不开的细节都做了出来。适合正在做即时通讯、消息推送、实时看板、在线协作类项目的开发者照着跑通之后换成自己的业务协议就能直接接进项目里。2. 整体架构与关键技术选型为什么用 Node.js 原生 ws 而不是 Socket.io2.1 技术栈与协议基础从 HTTP 到 WebSocket 的升级逻辑入手这份源码之前先理解它为什么这样选型。WebSocket 和 HTTP 的关系不是替代而是互补——HTTP 是“请求-响应”模型客户端不请求服务端就没法主动发数据WebSocket 则是在一次 HTTP 握手之后把连接升级成一条全双工的 TCP 通道双方随时可以往这条通道里写数据。这份实例源码服务端选用的是 Node.js 环境下的 ws 库没有使用 Socket.io。原因很务实Socket.io 虽然自带降级方案和自动重连但它封装层偏厚遇到二进制流、自定义协议头这些场景时会觉得“隔了一层”。原生 ws 更贴近协议底层连接状态、消息帧、心跳包都是自己可控的二次开发时也更容易替换成其他语言的服务端实现。// 服务端核心入口创建 WebSocket 服务并处理连接 const { WebSocketServer } require(ws); const wss new WebSocketServer({ port: 8080, path: /ws }); wss.on(connection, (ws, req) { // req.url 里可以携带 token 等鉴权参数 console.log([连接接入] 客户端: ${req.socket.remoteAddress}); ws.isAlive true; ws.on(pong, () { ws.isAlive true; }); });这段代码做了三件事实例化 WebSocketServer 并监听 8080 端口的/ws路径在 connection 回调里拿到握手请求对象 req方便后续读取 URL 参数做鉴权给每个连接对象挂上 isAlive 标记并监听 pong 事件为后面的心跳检测机制做准备。需要留意的参数是path: /ws它限制了只有访问/ws路径的请求才会升级为 WebSocket 连接这样做的好处是同一个端口上还可以继续提供 HTTP 接口服务互不干扰。2.2 目录结构与模块职责每个文件在该管什么拿到源码后第一件事不是看代码而是看目录结构。这份实例采用的是典型的“服务端 客户端 共享协议”三段式布局websocket-demo/ ├── server/ │ ├── index.js # 服务端入口创建服务、注册路由 │ ├── heartbeat.js # 心跳模块定时检测连接健康状态 │ ├── broadcast.js # 广播模块向所有连接推送消息 │ └── utils.js # 工具函数消息封装、日志输出 ├── client/ │ ├── index.html # 浏览器端测试页面 │ ├── client.js # 客户端封装连接、重连、心跳 │ └── style.css # 调试面板样式 ├── shared/ │ └── protocol.js # 前后端共用的消息协议常量 └── package.json服务端拆成四个文件目的是让连接管理、心跳逻辑、广播推送各自独立改造时不用在几百行的 index.js 里到处翻。client.js 是纯前端实现不依赖任何框架直接 script 标签引入就能用。shared/protocol.js 这个文件很容易被忽略但我建议你不要删——它把消息类型常量集中定义前后端共用同一份就不会出现“服务端发的是type: chat客户端判断的是msgType: chat”这种低级但对线上影响极大的不匹配问题。3. 核心模块拆解一个消息从客户端发出到服务端返回的完整链路3.1 消息协议设计JSON 格式与 type 字段的分发机制先看 shared/protocol.js这是整个系统能跑起来的“共同语言”。它定义了几种基础消息类型// shared/protocol.js const Protocol { // 客户端 - 服务端 C2S: { CHAT: chat, // 单聊消息 JOIN_ROOM: joinRoom, // 加入房间 LEAVE_ROOM: leaveRoom, // 离开房间 HEARTBEAT: ping // 心跳包 }, // 服务端 - 客户端 S2C: { CHAT: chat, // 聊天消息 SYSTEM: system, // 系统通知 HEARTBEAT: pong, // 心跳响应 ERROR: error // 错误信息 } }; function packMessage(type, payload {}) { return JSON.stringify({ type, payload, timestamp: Date.now() }); }packMessage 函数把每次要发送的数据统一封装成{ type, payload, timestamp }三个字段的结构。type 决定这个消息“是什么”payload 承载具体内容timestamp 记录发送时间既方便调试排查延迟问题也为后续做消息去重或排序提供了时间依据。这套设计在真实项目中几乎是标准做法你甚至可以把它直接搬进生产项目里。3.2 服务端消息处理从收到消息到广播给全部客户端的路由逻辑服务端收到消息后先解析 JSON再按 type 字段分发处理类似一个极简版的消息路由。看 index.js 里的核心处理逻辑ws.on(message, (data) { let msg; try { msg JSON.parse(data.toString()); } catch (e) { ws.send(packMessage(Protocol.S2C.ERROR, { message: 消息格式错误需要 JSON 字符串 })); return; } switch (msg.type) { case Protocol.C2S.CHAT: // 业务处理把收到的消息广播给所有在线客户端 wss.clients.forEach((client) { if (client.readyState WebSocket.OPEN) { client.send(packMessage(Protocol.S2C.CHAT, { from: msg.payload.from, content: msg.payload.content })); } }); break; case Protocol.C2S.HEARTBEAT: ws.send(packMessage(Protocol.S2C.HEARTBEAT, { time: Date.now() })); break; default: ws.send(packMessage(Protocol.S2C.ERROR, { message: 未知消息类型: ${msg.type} })); } });这里有个容易踩坑的细节遍历wss.clients时必须检查readyState是否为WebSocket.OPEN。原因在于wss.clients集合里可能包含正在关闭或已经关闭的连接直接调用 send 方法会抛异常。这也是我在前文提到“用原生 ws 更贴近协议底层”的体现——这些细节 Socket.io 帮你做了但你是看不见的出了问题只能把黑匣子当黑匣子处理毫无头绪。消息分发逻辑本身很直白解析失败则返回错误消息不直接断开连接给客户端一个容错机会CHAT 类型把消息广播给所有在线客户端HEARTBEAT 则立即回一个 pong保障心跳机制正常运作。3.3 心跳保活机制定时巡检 超时断连避免死连接拖死服务端心跳机制是这套源码里最值得反复读的部分。WebSocket 连接在 TCP 层面不会主动通知你“对端已经消失”比如手机 APP 被系统杀掉、Wi-Fi 切换到 4G这些场景下 TCP 连接可能还“活着”但实际已经联系不上对端了。如果不做清理这些“死连接”会一直占用服务端资源。心跳机制采取双向策略客户端定时发送 ping服务端回 pong同时服务端也定时检查所有连接的活跃状态// server/heartbeat.js function startHeartbeatCheck(wss, interval 30000) { const timer setInterval(() { wss.clients.forEach((ws) { if (!ws.isAlive) { // 连续两个周期没有收到 pong判定为死连接 ws.terminate(); return; } ws.isAlive false; // 先标记为 false等待下一次 pong 把它改回来 ws.ping(); // 主动发送 ping 帧 }); }, interval); wss.on(close, () clearInterval(timer)); return timer; }这段代码的巧妙之处在于先把所有连接标记为“可疑”只有主动 ping 且收到 pong 的连接才会被“平反”。这样即使某个客户端忘了发心跳服务端也能主动探测到连接状态。ws.ping()是 ws 库提供的方法发送的是 WebSocket 协议层面的控制帧不会干扰业务消息的收发。间隔时间interval是参数字段建议你根据实际场景调整——如果是手机端弱网环境30 秒太长改成 15 秒更稳妥如果是服务端之间的内网通信60 秒也完全可行。3.4 客户端封装自动重连、指数退避、心跳上报客户端的实现同样不是简单 new 一个 WebSocket 就完事而是封装了完整的状态管理// client/client.js class WSClient { constructor(url, options {}) { this.url url; this.reconnectAttempts 0; this.maxReconnectAttempts options.maxReconnectAttempts || 10; this.heartbeatInterval options.heartbeatInterval || 20000; this.ws null; this.listeners {}; } connect() { this.ws new WebSocket(this.url); this.ws.onopen () { console.log(连接已建立); this.reconnectAttempts 0; // 重置重连计数 this.startHeartbeat(); // 开启心跳定时器 }; this.ws.onclose () { console.log(连接关闭); this.stopHeartbeat(); this.reconnect(); // 触发重连逻辑 }; this.ws.onerror (err) { console.error(连接错误:, err); }; } reconnect() { if (this.reconnectAttempts this.maxReconnectAttempts) { console.error(重连次数已达上限请检查网络或服务端状态); return; } const delay Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000); const attempt this.reconnectAttempts; console.log(第 ${attempt} 次重连延迟 ${delay}ms); setTimeout(() this.connect(), delay); } startHeartbeat() { this.heartbeatTimer setInterval(() { this.send(Protocol.C2S.HEARTBEAT, {}); }, this.heartbeatInterval); } }重连策略使用指数退避算法第一次断开后 1 秒重连第二次 2 秒第三次 4 秒以此类推直到 30 秒封顶。这样做的目的是避免服务端故障恢复时几十个客户端同时疯狂重连形成“惊群效应”把服务端再次打垮。maxReconnectAttempts参数默认设了上限防止客户端在无网状态下无限重连耗尽手机电量——开发调试时可以调大生产环境建议维持这个限制。4. 避坑指南跑这份源码最容易遇到的 4 个问题4.1 现象客户端连接时报 404服务端完全没有收到请求原因path路径不匹配。如果服务端设置了path: /ws客户端连接地址就必须写成ws://localhost:8080/ws写成ws://localhost:8080会直接 404。解决统一使用目录中的shared/protocol.js里导出的配置常量来拼接地址而不是在 index.html 里手写 URL。如果必须要改路径服务端和客户端要同步修改建议做一个全局搜索确认两端一致。4.2 现象服务端向客户端发消息时抛错WebSocket is not open原因调用 send 方法时连接已经进入 CLOSING 或 CLOSED 状态。这个报错在遍历wss.clients广播消息时最常见因为你无法确定每个连接的真实状态。解决发送前必须判断client.readyState WebSocket.OPEN。如果你改写出更复杂的广播逻辑建议单独封装一个 safeSend 函数function safeSend(ws, data) { if (ws.readyState WebSocket.OPEN) { ws.send(data); } }4.3 现象浏览器端连接在 1 分钟左右被自动断开原因你的服务端部署在 Nginx 后面而 Nginx 默认的 proxy_read_timeout 是 60 秒。WebSocket 连接如果在这个时间内没有任何数据传输会被 Nginx 判定为超时并切断。这是 WebSocket 项目上生产环境时最高频的翻车点本地连没事一上服务器就断。解决在 Nginx 配置里加上长连接参数location /ws { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; }同时确认客户端心跳间隔小于 60 秒双重保障。4.4 现象服务端日志里频繁出现close事件但查不到业务报错原因心跳检测机制把某些“活着但没响应”的连接判定为死连接并执行了 terminate。这类情况多半是客户端页面切到了后台浏览器的定时器被降频心跳 ping 发送不及时。解决在前端监听 visibilitychange 事件页面切到后台时手动暂停心跳切回来时立即补发一次 ping 并重置心跳定时器。这个小改动能让后台页面的连接寿命明显延长。5. 本地运行与联调测试从 clone 到模拟 100 个并发连接5.1 环境准备与启动步骤Node.js 版本要求和依赖安装运行这份源码需要本机安装 Node.js。建议使用 14 及以上版本因为代码中用到了一些较新的 JavaScript 语法。依赖只有一个 ws 库安装成本极低# 在项目根目录执行 npm install # 启动服务端 node server/index.js看到终端输出[服务启动] WebSocket 服务已监听 8080 端口就说明服务端就绪了。然后直接用浏览器打开client/index.html页面会显示一个调试面板输入昵称后点击“连接”就能看到连接状态从 CONNECTING 变为 OPEN。5.2 双端联调用浏览器控制台模拟多客户端消息广播浏览器端的调试面板只能模拟一个客户端想验证消息广播机制最直接的方式是打开多个浏览器标签页。每个标签页独立建立一条 WebSocket 连接在其中任意一个页面发送消息其他页面都应该实时收到。如果想模拟更多并发连接不建议开几十个标签页——浏览器对同一域名的并发连接数是有限制的。更专业的做法是写一个简单的 Node 脚本压测// 使用 Node.js 内置的 WebSocket 客户端批量创建连接 const WebSocket require(ws); const total 100; const clients []; for (let i 0; i total; i) { const ws new WebSocket(ws://localhost:8080/ws); ws.on(open, () { ws.send(JSON.stringify({ type: chat, payload: { from: user-${i}, content: hello } })); }); clients.push(ws); } setTimeout(() { clients.forEach(c c.close()); process.exit(0); }, 10000);这个脚本会创建 100 条连接并向服务端发送消息。运行后观察服务端日志确认所有连接都正常建立和收发消息没有出现内存溢出或事件循环阻塞。压测时重点关注服务端内存和 CPU 占用如果内存持续增长不回落大概率是消息监听器没释放需要检查代码里是否有 addEventListener 后忘记 remove 的情况。6. 二次开发把这份源码改造成带鉴权和消息类型的 IM 系统6.1 第一步连接时校验身份——把 token 放进握手请求当前源码的连接是匿名的任何客户端都可以直接连上来。改造的第一步是加上鉴权。推荐的做法是把 token 放在 URL 查询参数里服务端在 connection 回调中校验// server/index.js 改造 const url require(url); wss.on(connection, (ws, req) { const params url.parse(req.url, true).query; const token params.token; if (!token || !verifyToken(token)) { ws.close(4001, 未经授权的连接); return; } // 通过鉴权继续后续逻辑 ws.userId getUserIdFromToken(token); });verifyToken 函数里你可以接 Redis 会话、JWT 解析或者数据库查询只需要返回布尔值和用户 ID。注意 ws.close 的第二个参数要求是字符串它会作为关闭原因发送给客户端方便客户端判断重连策略——比如收到 4001 就不应该自动重连而收到 1006 这种异常断开则应该立即重试。6.2 第二步从广播改成点对点——用 userId 精确定位接收方当前所有消息都是广播给所有客户端这在真实场景中不现实。改造的核心是通过 userId 维护一个“在线用户表”const onlineUsers new Map(); wss.on(connection, (ws, req) { // 假设上一步鉴权已经拿到了 ws.userId onlineUsers.set(ws.userId, ws); ws.on(close, () { onlineUsers.delete(ws.userId); }); }); // 点对点发送 function sendToUser(userId, message) { const targetWs onlineUsers.get(userId); if (targetWs targetWs.readyState WebSocket.OPEN) { targetWs.send(message); } }Map 结构做用户映射天然合适查找和删除都是 O(1) 复杂度。注意在 close 时清理 Map否则长时间跑会产生内存泄漏。如果用户量很大单机 Map 不够用就需要引入 Redis 的 Pub/Sub 机制做跨节点消息路由这就是后话了。6.3 第三步加入房间分组——支持多人会话和群聊在点对点基础上再扩展一层房间分组就接近一个可用的 IM 核心了const rooms new Map(); // roomId - Setws function joinRoom(roomId, ws) { if (!rooms.has(roomId)) { rooms.set(roomId, new Set()); } rooms.get(roomId).add(ws); } function broadcastToRoom(roomId, message) { const room rooms.get(roomId); if (!room) return; room.forEach(ws { if (ws.readyState WebSocket.OPEN) { ws.send(message); } }); }房间数据结构和在线用户表类似只是 value 从单个 WebSocket 换成了 Set 集合。配合前文的鉴权你来设计群聊消息协议时只需要在 payload 里加上 roomId 字段服务端收到消息后调用 broadcastToRoom 即可。这套源码最让我满意的地方是它没有过度封装每个机制都看得见摸得着。我第一次拿它改生产项目时就是照着心跳模块重写了一套适合弱网环境的长连接方案直接把移动端消息到达率提高了不少。从那以后我每次搭 WebSocket 服务都强制自己先画一张连接生命周期图——从握手、鉴权、心跳、重连到关闭每一步的状态和触发条件全标出来然后再写代码至少能少踩一半的坑。希望这套源码和这篇解析能帮到你。本文还有配套的精品资源点击获取

相关新闻

Git 命令实战手册:从版本控制基础到分支管理、远程协作与错误恢复

Git 命令实战手册:从版本控制基础到分支管理、远程协作与错误恢复

1. 关于 Git 命令这件事,先聊几句实在话作为一个每天跟代码打交道的开发者,Git 大概是我用得最多的工具之一。很多人觉得 Git 命令又多又杂,记不住、用不好,甚至有人跟我说"能跑就行,能提交就行"。但实际上&…

2026/10/18 12:38:31 阅读更多 →
多通道残差连接:深层网络训练更稳定的工程化方案

多通道残差连接:深层网络训练更稳定的工程化方案

元旦刚过,技术社区里最热的一条讨论,就是新的多通道残差连接方案。大家关心的倒不是某个Block的命名有多酷,而是这套结构真的把“更稳定”这三个字落到了实处:深层网络的梯度不容易断,训练曲线的波动变小,同等参数量下可以更安全地堆更多层。说白了,咱们平时堆ResNet、堆Transf…

2026/10/18 12:38:31 阅读更多 →
高德交通态势爬取实战:Python采集道路级速度与拥堵等级数据

高德交通态势爬取实战:Python采集道路级速度与拥堵等级数据

简介:面向交通数据分析、城市规划与GIS应用开发者,这份高德交通态势爬取资源使用脚本调用高德地图接口,获取实时路况、拥堵指数等态势信息,并兼顾请求限速与反爬策略,可直接用于后续交通流分析及ArcGIS空间数据预处理。…

2026/10/18 12:37:31 阅读更多 →

最新新闻

Linux下NVML初始化失败:驱动与库版本不匹配的排查与修复指南

Linux下NVML初始化失败:驱动与库版本不匹配的排查与修复指南

1. 这个报错到底在说什么Failed to initialize NVML: Driver/library version mismatch这行字,但凡在 Linux 上跑过深度学习训练、折腾过显卡直通、或者手贱升级过一次系统内核的人,大概率都见过。它的字面意思很直白:NVML 初始化失败&#x…

2026/10/18 13:26:59 阅读更多 →
迈迪三维设计工具:SolidWorks国标件参数化建模加速方案

迈迪三维设计工具:SolidWorks国标件参数化建模加速方案

简介:迈迪三维设计工具集是专为SolidWorks平台开发的专业级机械设计辅助插件,面向机械工程师、产品设计师及高校相关专业师生,旨在提升标准件建模、结构设计与工程图生成效率。资源包共2000个文件,总大小211.97MB,涵盖…

2026/10/18 13:26:59 阅读更多 →
JDBC从入门到精通:连接、预编译、事务与连接池实战

JDBC从入门到精通:连接、预编译、事务与连接池实战

做Java开发的朋友,应该都对JDBC不陌生。它就像是Java世界和数据库之间的一座桥,不管是传统的业务系统,还是后面对接MyBatis、Hibernate这类ORM框架,底层真正干活的还是JDBC。可以说,只要你想在Java里操作数据库&#x…

2026/10/18 13:26:59 阅读更多 →
如何查看电脑开机时间?四种系统自带方法实测与解读

如何查看电脑开机时间?四种系统自带方法实测与解读

1. 为什么非要搞清楚电脑的开机时间先说个场景,不知道你有没有遇到过:新装了一台电脑,或者刚重做完系统,总感觉开机慢得像老牛拉车。这时候你想评估一下到底是硬件不行,还是系统没优化好,最直接的一个指标就…

2026/10/18 13:26:59 阅读更多 →
Linux下NVIDIA驱动NVML版本不匹配报错排查与修复指南

Linux下NVIDIA驱动NVML版本不匹配报错排查与修复指南

1. 这个报错到底在说什么如果你在 Linux 环境下用nvidia-smi查显卡状态,终端冷不丁甩出一句Failed to initialize NVML: Driver/library version mismatch,那基本可以确定一件事:你机器上正在运行的 NVIDIA 内核驱动版本,和你当前…

2026/10/18 13:26:59 阅读更多 →
Java在线教育平台源码解析:DWD-DWS-DIM分层架构与毕设实战指南

Java在线教育平台源码解析:DWD-DWS-DIM分层架构与毕设实战指南

简介:这是一套面向Java开发者与教育信息化建设者的在线教育平台6.2版本完整设计源码,聚焦教学管理、课程学习、在线考试与数据治理等核心场景,适用于高校IT课程实践、教育类毕业设计或中小型在线教育系统二次开发。资源共69个文件&#xff0c…

2026/10/18 13:25:59 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →