# 第一阶段 · 模块一 · 第十一节:Remote Session 远程会话
Claude Code 如何实现远程会话?Remote Session 的工作原理是什么?WebSocket 通信机制是什么?如何保证会话状态同步?
Claude Code 全局架构
┌─────────────────────────────────────────────────────────────────────┐
│ 网络层(network/) │
│ │
│ Remote Session ← 本节 │
│ ├── WebSocket 通信 │
│ ├── 会话同步 │
│ ├── 状态管理 │
│ └── 断线重连 │
└─────────────────────────────────────────────────────────────────────┘
源码位置:`src/services/remote/`
Remote Session 允许用户通过浏览器或其他客户端远程连接到 Claude Code 实例,实现跨设备的 AI 编程体验。
┌─────────────────────────────────────────────────────────────────────┐
│ Remote Session 架构 │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Browser │◄────────────►│ Claude Code │ │
│ │ (Web UI) │ WebSocket │ Server │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ Remote Session 功能 │
│ │
│ 1. 远程访问 │
│ - 通过浏览器访问 Claude Code │
│ - 无需本地安装 │
│ │
│ 2. 会话同步 │
│ - 实时同步终端状态 │
│ - 多设备同步 │
│ │
│ 3. 协作功能 │
│ - 多人同时访问 │
│ - 共享会话 │
└─────────────────────────────────────────────────────────────────────┘
问 1:Remote Session 和本地终端有什么区别?
// 本地终端:
// - 直接运行在本地
// - 无网络延迟
// - 需要本地安装
// Remote Session:
// - 通过浏览器访问
// - 有网络延迟
// - 无需本地安装
// - 支持跨设备
源码位置:`src/services/remote/websocket.ts`
// WebSocket 连接建立
async function connectToRemote(
url: string,
token: string
): Promise<WebSocket> {
// 1. 建立 WebSocket 连接
const ws = new WebSocket(url, {
headers: { Authorization: `Bearer ${token}` }
})
// 2. 等待连接打开
await new Promise((resolve, reject) => {
ws.onopen = resolve
ws.onerror = reject
})
// 3. 返回 WebSocket 实例
return ws
}
// Remote Session 消息格式
type SessionMessage =
| { type: 'input'; data: string } // 终端输入
| { type: 'output'; data: string } // 终端输出
| { type: 'resize'; cols: number; rows: number } // 终端大小
| { type: 'status'; status: 'connected' | 'disconnected' } // 连接状态
// 心跳保活
// 定期发送 ping
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping' }))
}
}, 30000)
// 处理 pong
ws.on('pong', () => {
lastPong = Date.now()
})
问 1:为什么需要心跳机制?
// 心跳机制的作用:
// 1. 检测连接状态
// - 及时发现断线
// - 避免僵尸连接
// 2. 保持连接活跃
// - 防止 NAT 超时
// - 避免中间设备断开
// 3. 网络质量监测
// - 记录延迟
// - 评估连接稳定性
源码位置:`src/services/remote/stateSync.ts`
// 会话状态
interface SessionState {
sessionId: string
terminalBuffer: string[] // 终端缓冲区
cursorPosition: { x: number; y: number }
currentDirectory: string
environment: Record<string, string>
}
// 状态持久化
// 1. 本地缓存
// - 会话状态保存在内存
// - 定期写入磁盘
// 2. 恢复机制
// - 断线重连后恢复状态
// - 同步缺失的输出
冲突处理策略:
┌─────────────────────────────────────────────────────────────────────┐
│ 多客户端同步 │
│ │
│ 1. 最后写入胜出 │
│ - 以时间戳判断 │
│ - 简单但可能丢失操作 │
│ │
│ 2. 客户端标记 │
│ - 每个客户端有唯一 ID │
│ - 操作带有来源标记 │
│ │
│ 3. 操作转换 │
│ - OT 算法 │
│ - 复杂但一致性最强 │
└─────────────────────────────────────────────────────────────────────┘
源码位置:`src/services/remote/reconnect.ts`
// 指数退避重连
async function reconnect(
maxRetries: number = 5,
baseDelay: number = 1000
): Promise<void> {
for (let i = 0; i < maxRetries; i++) {
try {
await connectToRemote(url, token)
return // 连接成功
} catch (error) {
// 指数退避
const delay = baseDelay * Math.pow(2, i)
await sleep(delay)
}
}
throw new Error('Max retries exceeded')
}
// 断线重连后的状态恢复
async function onReconnect(ws: WebSocket): Promise<void> {
// 1. 请求服务器发送缺失的状态
ws.send(JSON.stringify({
type: 'sync',
lastSequence: lastKnownSequence
}))
// 2. 接收并应用状态差异
const diff = await receiveStateDiff()
applyStateDiff(diff)
// 3. 恢复正常操作
resumeNormalOperation()
}
问 1:断线期间的操作会丢失吗?
// 取决于操作类型:
// 1. Claude 执行的操作
// - 服务器端已执行
// - 重连后可恢复
// 2. 用户输入
// - 客户端本地缓存
// - 重连后重新发送
// 3. 实时交互
// - 可能丢失关键部分
// - 需要人工处理
// 认证机制
// 1. Token 认证
// - 一次性 URL token
// - 或长期访问 token
// 2. 密码保护
// - 可选的会话密码
// - 防止未授权访问
┌─────────────────────────────────────────────────────────────────────┐
│ 安全措施 │
│ │
│ 1. WSS 加密 │
│ - WebSocket over TLS │
│ - 防止中间人攻击 │
│ │
│ 2. 端到端加密 │
│ - 可选的端到端加密 │
│ - 服务器无法解密 │
│ │
│ 3. 会话隔离 │
│ - 每个会话独立隔离 │
│ - 防止跨会话访问 │
└─────────────────────────────────────────────────────────────────────┘
# 启动远程会话服务器
claude --remote --port 8080
# 获取访问 URL
# 输出:https://localhost:8080/session/abc123
# 或使用 ngrok 暴露到公网
ngrok http 8080
访问流程:
1. 打开浏览器访问 URL
↓
2. 输入访问密码(如有)
↓
3. 建立 WebSocket 连接
↓
4. 同步会话状态
↓
5. 开始远程操作
答案:
// 适用场景:
// 1. 云端开发
// - 服务器上有更好的资源
// - 无需本地配置
// 2. 跨设备工作
// - 手机/平板编程
// - 临时使用他人电脑
// 3. 协作教学
// - 老师演示
// - 学生观察
// 4. 安全隔离
// - 不希望在本地存储代码
// - 云端审计追踪
答案:
// 优化方法:
// 1. 网络优化
// - 使用更近的服务器
// - 启用压缩
// 2. 终端优化
// - 减少屏幕刷新
// - 调整终端大小
// 3. 协议优化
// - 使用二进制协议
// - 减少消息开销
// 4. 本地缓存
// - 缓存历史输出
// - 减少重复传输
答案:
// 安全措施:
// 1. 认证
// - 使用一次性 URL token
// - 或长期访问 token
// 2. 加密
// - WSS 加密传输
// - 端到端加密可选
// 3. 会话隔离
// - 每个会话独立
// - 防止跨会话访问
// 4. 审计
// - 记录所有操作
// - 支持回放审计
答案:
// 重连策略:
// 1. 指数退避
// - 初始延迟: 1秒
// - 最大延迟: 30秒
// - 退避倍数: 2
// 2. 最大重试
// - 限制重试次数
// - 超过后通知用户
// 3. 状态同步
// - 重连后获取缺失状态
// - 使用 sequence number
// 4. 用户体验
// - 显示重连状态
// - 提供手动重连按钮
| 资源 | 说明 |
| `src/services/remote/websocket.ts` | WebSocket 通信 |
| `src/services/remote/stateSync.ts` | 状态同步 |
| `src/services/remote/reconnect.ts` | 重连机制 |
下一节我们将进入 Context Providers 上下文提供者:
- React Context 架构
- 状态管理
- 跨组件通信