手机远程控制电脑 — 技术原理与核心概念
本文档聚焦于原理:手机远程控制 Claude Code CLI / AI Agent 涉及的关键技术概念、通信协议、系统机制和网络原理。理解这些概念后,后续实操文档中的每一步操作都会变得有据可依。
一、两种需求,同一套原理
远程控制涉及两个不同的场景,但底层的技术原理是相通的:
场景 A — 自建 Agent 的远程操控接口
你正在开发自己的 AI Agent(直接调用 API,非终端程序),想在手机上查看 Agent 运行状态、下发任务、审批工具调用。这个场景天然需要 WebSocket 实现双向实时通信。
场景 B — 远程操作 Claude Code CLI
你已经在电脑上使用 Claude Code CLI 进行开发,想从手机上输入指令、查看输出、中断任务。这个场景的核心是把手机变成一个远程终端。
本文档聚焦于原理,不深入具体场景的工程实现。下面要讲的概念——WebSocket、PTY、NAT、tmux、SSH——是两个场景共同依赖的技术基础。理解它们,后续实操才能知其所以然。
二、通信协议:HTTP 与 WebSocket
1. HTTP(超文本传输协议)
比喻:寄信
- 你(手机)写一封信(请求),扔进邮筒,等邮递员送到对方(电脑)。
- 对方看完,写回信,再寄回来。
- 关键:每封信都是独立的,邮递员不记得你上一封信写了什么。
特点:
- 请求-响应模式,客户端主动问,服务器被动答
- 服务器无法主动推送数据
- 每次请求独立,不适合持续流式输出
2. WebSocket
比喻:打电话
- 你拨通电话(建立连接),双方一直保持通话(连接不断开)。
- 随时说话,随时听,双向实时。
特点:
- 一次连接,持续在线
- 双向实时通信,服务器能主动推数据
- 适合流式输出场景
3. 两者的角色分工
远程控制场景中,HTTP 和 WebSocket 各司其职,缺一不可:
| 组件 | 作用 | 是否必须 |
|---|---|---|
| HTTP | 提供用户界面(加载 HTML 页面:输入框、按钮、显示区域) | 必须(除非用 Telegram 等替代) |
| WebSocket | 传输指令和实时输出 | 必须 |
典型流程:
- 手机浏览器用 HTTP 访问
http://电脑IP:8080,加载页面 - 页面里的 JavaScript 自动建立 WebSocket 连接
- 用户通过页面操作,JS 通过 WebSocket 发指令、收输出
4. 为什么远程控制必须用 WebSocket?
如果用 HTTP 来实现 Claude Code 的远程控制:
- 你发"帮我写个 Python 脚本"
- Claude 开始思考、写代码、运行测试,输出几十行中间结果
- 你需要不断"发新信去问'现在进度如何?'",极其低效
用 WebSocket:一次连接,Claude 的所有输出都会实时推送到你手机。
三、WebSocket 的本质与实现
1. 本质
WebSocket 是一种建立在 TCP 之上的全双工通信协议。它通过一次 HTTP 握手升级为持久连接,之后不再需要 HTTP 头部的开销。
2. 各端支持情况
手机浏览器(控制端):
现代手机浏览器原生支持 WebSocket,无需安装任何东西:
| 浏览器 | 支持情况 |
|---|---|
| iOS Safari | iOS 7(2013年)起完全支持 |
| Android Chrome | Chrome 16(2011年)起完全支持 |
| 其他移动浏览器 | 全部支持 |
手机浏览器里的 JavaScript 可以直接调用:
const ws = new WebSocket('ws://192.168.1.100:8080');
ws.onmessage = (e) => console.log(e.data);
Node.js/Electron(被控端):
Node.js 没有内置 WebSocket API,需要安装第三方库(最常用的是 ws):
npm install ws
3. Electron 的特殊优势
| 环境 | 系统权限 | 能否启动子进程? |
|---|---|---|
| 浏览器 JavaScript | 沙箱,无文件系统权限 | 不能 |
| Node.js | 完整系统权限 | 能 |
| Electron | 浏览器 + Node.js 混合 | 能 |
Electron 应用可以:
- 启动子进程运行
claude命令 - 读写本地文件
- 监听端口作为 WebSocket 服务器
四、信息传播的完整路径
[你的手指在手机屏幕上点击"运行"按钮]
↓
[手机 App / 网页] 构造一条文本消息:"run: 帮我写一个计算器"
↓
[手机的 WebSocket 客户端] 把这行文本通过已建立的连接发送出去
↓ (穿越 Wi-Fi 路由器)
[电脑的 Electron 应用] WebSocket 服务器收到消息
↓
[Electron 主进程] 解析消息,识别出"运行 Claude 命令"
↓
[Electron 启动子进程] 执行 `claude "帮我写一个计算器"`
↓
[Claude CLI] 开始运行,输出第一行:"好的,我来帮你写..."
↓
[Electron 监听到子进程的 stdout] 收到这行输出
↓
[Electron 通过 WebSocket] 把这行输出实时推送给手机
↓ (穿越 Wi-Fi 路由器)
[手机的 WebSocket 客户端] 收到消息
↓
[手机 App / 网页] 把这条消息显示在屏幕上
关键点:整个过程双向实时,就像聊天。Claude 的输出是流式的,每输出一行就立即推送。
五、终端与进程原理
远程控制 CLI 的本质是:把手机变成一个远程的"键盘+屏幕"。要理解这是怎么做到的,需要先理解终端、进程、输入输出之间的关系。
1. 什么是 PTY(伪终端)
PTY(Pseudo Terminal,伪终端)是操作系统提供的一对虚拟设备:
- PTY master(主设备):连接终端模拟器(或手机界面),接收用户的键盘输入,发送程序的屏幕输出
- PTY slave(从设备):连接 CLI 程序(如 Claude Code),让它"以为"自己在真实的终端里运行
关键理解: CLI 程序不关心数据来自物理键盘还是网络连接——它只和 PTY slave 通信。这意味着,只要把网络数据注入 PTY master,程序就会以为是用户在本地操作。
2. 标准输入输出
程序启动后,操作系统为其分配三个数据流:
| 流 | 名称 | 比喻 | 方向 |
|---|---|---|---|
| stdin (0) | 标准输入 | 程序的"耳朵" | 输入流向程序 |
| stdout (1) | 标准输出 | 程序的"嘴巴" | 输出流向屏幕 |
| stderr (2) | 标准错误 | 程序的"另一张嘴" | 错误信息流向屏幕 |
在远程控制场景中:
手机发送的文字 → 网络 → PTY master → PTY slave → 程序的 stdin
程序的 stdout/stderr → PTY slave → PTY master → 网络 → 手机屏幕
3. 信号(Signal)
信号是操作系统通知进程"发生了某件事"的机制。最常见的是:
| 信号 | 触发方式 | 含义 |
|---|---|---|
| SIGINT | Ctrl+C |
中断当前程序 |
| SIGTERM | kill 命令 |
请求程序终止 |
| SIGKILL | kill -9 |
强制终止(程序无法忽略) |
| SIGHUP | 终端断开 | 挂起信号,默认终止程序 |
远程中断的原理:
- 手机点击"中断"按钮
- WebSocket 向电脑发送一个特殊消息
- 电脑端向 PTY 写入
Ctrl+C字符(ASCII0x03) - PTY 检测到控制字符,向子进程发送 SIGINT 信号
- Claude Code 收到信号,停止当前任务
这就是为什么远程控制不能只靠文本传输——你还需要一个能往 PTY 注入控制字符的通道。
4. Claude Code 作为交互式 CLI
Claude Code 是一个交互式 CLI 程序:
- 启动后附着在 PTY 上
- 从 stdin 读取用户消息
- 往 stdout 流式输出回复
- 等待用户下一步指令
因此,远程控制 Claude Code 等价于:通过网络把一个 PTY 投射到手机上。无论是 WebSocket、SSH 还是 tmux,背后的原理都是 PTY 的输入输出重定向。
六、网络穿透原理
1. 为什么电脑没有公网 IP?
绝大多数家庭宽带用户没有真正的公网 IPv4 地址:
- IPv4 地址枯竭(全球约 42 亿个),运营商通过 NAT(网络地址转换) 让多个用户共享一个公网 IP
- 你电脑拿到的 IP(如
192.168.x.x或100.x.x.x)是内网 IP,在互联网上不可路由
NAT 的原理:
- 你电脑访问百度时,请求经过路由器,路由器把内网 IP 换成自己的公网 IP,同时记下"这个连接是从哪台内网设备来的"
- 百度的回复到达路由器,路由器查记录,转发回你的电脑
- 但外网设备无法主动连接到你电脑——路由器不知道该把连接请求转发给谁
判断方法: 手机用 4G 访问你电脑的 IP 地址,连不上——说明你没有公网 IP。
2. 核心解决方案对比
| 方案 | 原理 | 手机端 | 电脑端 | 适用场景 |
|---|---|---|---|---|
| 同一 Wi-Fi | 局域网直连 | 浏览器即可 | 无额外要求 | 在家测试 |
| Tailscale | 虚拟组网(WireGuard 加密) | 安装 App | 安装 Tailscale | 日常使用 |
| ngrok | 公网中转隧道 | 浏览器即可 | 安装 ngrok | 临时分享 |
| Cloudflare Tunnel | 公网中转隧道 | 浏览器即可 | 安装 cloudflared | 有域名 |
| 公网 IP + 端口转发 | 路由器直接暴露 | 浏览器即可 | 需公网 IP + 配置 | 有公网 IP |
3. Tailscale(推荐方案)
原理:
- 给你的电脑分配一个虚拟 IP(如
100.64.0.1) - 手机连上 Tailscale 后,就能用这个虚拟 IP 访问电脑
- 就像永远在一个 Wi-Fi 下
技术基础: Tailscale 基于 WireGuard 协议,使用现代加密技术直接在设备之间建立加密隧道。连接是点对点的,不经过中心服务器(除了最初的协调阶段),所以延迟低、带宽高。
优点: 免费、稳定、安全、P2P 直连延迟低。
缺点: 需要用户安装和注册。
4. ngrok(中转隧道)
原理:
- 电脑运行
ngrok tcp 8080,ngrok 客户端主动连接到 ngrok 公网服务器(出站连接,防火墙不阻挡) - ngrok 服务器分配一个公网地址(如
0.tcp.ngrok.io:12345) - 手机访问这个地址 → ngrok 服务器 → 转发到电脑
缺点: 免费版域名/端口随机,每次重启 ngrok 会变。
5. Cloudflare Tunnel
原理和 ngrok 相似,但使用 Cloudflare 的全球网络。优势是可以绑定自己的域名、不需要开放端口、集成 Cloudflare 安全防护。
七、会话持久化与 tmux
1. 没有会话持久化的后果
打开终端 → 运行 Claude Code → 关掉终端 → Claude Code 终止
手机连上去 → 一切从头开始
网络中断、浏览器意外关闭、电脑休眠——这些都会导致任务丢失。
2. tmux 的原理
tmux(Terminal Multiplexer,终端复用器)的核心机制是 持有 PTY:
正常终端:
终端窗口 ←→ PTY ←→ CLI 程序
窗口关闭 → PTY 销毁 → 程序终止
有 tmux:
tmux 会话 ←→ PTY ←→ CLI 程序
tmux 在后台作为一个守护进程运行
网络断开 → tmux 仍在后台 → PTY 健在 → 程序继续运行
重新连上 → tmux attach → 重新接入 PTY → 看到最新状态
通俗理解: tmux 在后台开了一个"虚拟终端房间",你随时可以进去、出来,房间和里面运行的程序一直存在。
3. tmux 与同类工具对比
| 工具 | 原理 | 能否重连 | 多窗口 |
|---|---|---|---|
| nohup | 让进程忽略 SIGHUP 信号 | 不能 | 单进程 |
| screen | 早期终端复用器 | 能 | 支持 |
| tmux | 现代终端复用器,基于 PTY | 能 | 支持 |
4. tmux 的核心价值
| 场景 | 没有 tmux | 有 tmux |
|---|---|---|
| 手机浏览器意外关闭 | Claude 可能终止 | 重新打开网页,接上继续 |
| 网络断线 | 任务中断 | 任务继续在后台跑 |
| 断开后想看之前的输出 | 看不到 | 滚动缓存还在 |
八、SSH 远程控制原理
实操指南中使用 SSH 作为远程控制手段。理解 SSH 的原理,有助于理解为什么它适合这个场景,以及它和 WebSocket 方案有什么异同。
1. SSH 的本质
SSH(Secure Shell,安全外壳协议)是一种加密的远程终端协议。它做的事情很简单:
- 在手机和电脑之间建立一条加密通道
- 把手机的键盘输入通过这条通道送到电脑的终端
- 把电脑终端的屏幕输出通过这条通道送回手机
2. 加密握手过程
SSH 的连接建立分为三个阶段:
第一阶段:密钥交换
- 客户端和服务器协商加密算法
- 使用 Diffie-Hellman 算法生成一个临时会话密钥(双方各自计算,网络上不传输这个密钥本身)
- 之后的通信都使用这个会话密钥加密
第二阶段:身份认证
- 密码认证:客户端加密发送密码,服务器验证
- 密钥认证:客户端用私钥签名一个质询,服务器用公钥验证(更安全,实操指南中的方案)
第三阶段:建立会话
- 认证通过后,服务器为客户端创建一个 PTY
- 所有的键盘输入和屏幕输出都通过加密通道在 PTY 之间传输
3. SSH 端口转发(隧道)
SSH 不仅能提供远程终端,还能转发 TCP 连接:
| 转发类型 | 命令 | 作用 |
|---|---|---|
| 本地转发 | ssh -L |
把远程端口映射到本地 |
| 远程转发 | ssh -R |
把本地端口映射到远程(可用于穿透内网) |
| 动态转发 | ssh -D |
创建 SOCKS 代理 |
4. 为什么 SSH 天然适合远程控制 CLI?
SSH 的设计初衷就是"远程终端",所以它天然具备远程控制 CLI 所需的一切:
| 远程控制需求 | SSH 的对应能力 |
|---|---|
| 双向实时通信 | SSH 建立在 TCP 之上,全双工 |
| 终端控制字符 | SSH 通过 PTY 传输所有字符(包括 Ctrl+C、Tab 补全等) |
| 加密安全 | 所有通信加密,防止中间人攻击 |
| 网络穿透 | 结合 Tailscale 或远程转发,轻松穿透 NAT |
SSH 与 WebSocket 方案的本质联系:
- WebSocket 方案是自己搭建通信通道 + 自己处理 PTY
- SSH 方案是直接用 SSH 协议替代了"通信通道 + PTY"这整层
- 两者底层的理论完全相同:网络 + PTY + stdin/stdout
九、架构模式:P2P 直连 vs Gateway 调度
P2P 直连
手机 ←→ 电脑(WebSocket 服务器 + Claude)
优点: 简单,完全掌控。
缺点: 需要处理网络穿透,手机端需要 UI。
Gateway 居中调度
手机 → Telegram 服务器 → Gateway(云服务器) → 电脑节点
↓
其他设备节点
本质区别: 引入 Gateway 作为统一接入层。Gateway 负责接收所有消息渠道(Telegram、Discord、Web 等),管理所有设备节点,处理会话状态、权限控制和任务调度。
十、关键术语表
| 术语 | 解释 |
|---|---|
| WebSocket | 网络协议,建立在 TCP 之上的全双工通信通道,像"打电话" |
| HTTP | 网络协议,请求-响应模式,像"寄信" |
| PTY | 伪终端(Pseudo Terminal),操作系统提供的一对虚拟设备,让 CLI 程序以为自己运行在真实终端里 |
| stdin/stdout/stderr | 标准输入/输出/错误,进程的三个数据流 |
| SIGINT | 中断信号,Ctrl+C 触发,告诉程序停止当前工作 |
| SSH | 安全外壳协议,加密的远程终端协议 |
| Tailscale | 虚拟组网工具,基于 WireGuard,给设备分配虚拟 IP |
| WireGuard | 现代 VPN 协议,简洁、高速、加密 |
| ngrok | 内网穿透工具,通过公网中转服务器暴露本地服务 |
| NAT | 网络地址转换,让多个设备共享一个公网 IP,但也阻挡了外网主动连接 |
| tmux | 终端复用器,持有 PTY,让会话断开后能再接上 |
| Gateway | 网关,统一接入层,管理消息渠道和设备节点 |
| 内网穿透 | 让没有公网 IP 的设备能被外网访问的技术统称 |
| Diffie-Hellman | 密钥交换算法,双方在不安全的通道上协商出共享密钥 |
十一、核心认知总结
-
WebSocket 是远程控制的关键,因为需要双向实时通信。HTTP 做不到。
-
手机浏览器原生支持 WebSocket,不需要装任何东西。但 Node.js 需要装
ws库。 -
远程控制 CLI 的本质是把手机变成一个远程 PTY 的输入输出接口。
-
PTY 是连接网络和 CLI 程序的桥梁——CLI 程序只认 PTY,不认网络。网络数据必须通过 PTY 才能让程序"听懂"。
-
信号传递是远程控制的重要组成部分,中断(Ctrl+C)需要往 PTY 注入控制字符,只发文本消息是不够的。
-
电脑没有公网 IP 是常态,需要 Tailscale/ngrok 等工具解决网络穿透。Tailscale 基于 WireGuard,P2P 直连延迟最低。
-
tmux 让远程会话持久化——它的本质是持有一个 PTY,即使网络断开,程序仍在后台运行。
-
SSH 天然适合远程 CLI 控制——它把"加密通信通道 + PTY"打包成了一个成熟的协议。
-
SSH 和 WebSocket 方案底层原理相同:都是通过网络传输 PTY 的输入输出,差异在协议层和实现复杂度。
-
P2P 与 Gateway 是两种架构模式,P2P 简单直接,Gateway 适合多设备多通道场景。