ARTICLE · 1347864
手机不装 App 怎么进内网聊天?我把整个 Web 服务塞进了一个 exe
内网 IM 的最后一台设备永远是手机。这篇讲我们怎么让手机浏览器扫码即用——不装 App、不加服务器,顺手把安全、实时推送、文件传输的设计取舍全聊了。
先说困境。
桌面端稳定运行之后,真实的诉求来了:人在产线、会议室、走廊,电脑不在手边,但手机都在。怎么让手机收发内网消息、传文件?
装 App 这条路在企业内网基本是死路:没有应用商店分发渠道,安卓要处理"未知来源",iOS 更是无解。就算装上了——上一篇聊过,给散装终端做自动更新有多难。
微信也不能用:内网文件进外网,就是安全事故。
剩下唯一一条零成本通道:手机自带的浏览器。预装率百分之百,不用分发,不用更新,扫码即用。
目标定成三条:
手机扫码打开网页,能收发消息、收发文件; 不新增部署单元,Web 服务内嵌在桌面端进程里; 内网不是可信网络,安全默认值按最坏情况设。
连网页都编译进 exe
我们的分发哲学是"单二进制、拷过去就能跑"。Web 端不能破例:网页文件在编译期直接嵌进 exe,没有静态资源目录。
好处是消灭了一整类问题:不存在"忘了拷 web 文件夹",不存在"升级后 exe 和网页版本不同步"。桌面版 exe 同时就是 Web 服务端,一个文件两用。
端口从 8080 起逐个试绑,被占用就自动避让——和别的实例共存在一台机器上也不打架。
安全的三个默认值
令牌每次启动随机重生。二维码里带着一个随机访问令牌。为什么不用固定口令?因为固定口令一定会被截图转发——群聊里发一次,链接就永久有效,离职同事手机里还躺着一张能看你内网聊天记录的图。
改成每次启动重生,效果是泄漏会自愈:电脑重启一次,所有外流的旧链接集体失效。代价是大家重新扫一次码——这个交换明显划算。
鉴权留了两条通道。页面内的请求走标准的令牌请求头,这没问题。但文件下载是点链接打开的——浏览器的页面跳转带不了自定义请求头。如果只支持请求头,手机上点"下载"就是一片 401。
所以必须有"链接直接带令牌"这第二条通路。安全设计和可用性的交点,经常就藏在这种框架限制的细节里。
文件名单元化,防目录穿越。Web 端能传文件,意味着 URL 里的文件名是不可信输入。原则:文件名只当纯名字用,带路径语义的一律拒收——../../etc、..\evil、C: 全打回。上传落盘和下载读取共用同一个闸门,不留侧门。
实时推送:为什么不用 WebSocket
第一版手机页面是 3 秒一次盲轮询——能用,但消息最多延迟 3 秒,空转请求还刷日志。
要"秒级到达",候选三个:WebSocket、SSE、长轮询。效果上都是秒级到达,成本上差远了——前两个要大改 HTTP 底层(我们的响应体不支持流式推送),长轮询零改造:
请求挂起,最多等 25 秒;服务器有事件(新消息、在线状态变化)立即返回;页面收到响应后紧接着再挂上。
对用户来说,消息到达就是秒级的。技术选型不是选最先进的,是选最便宜的够用解。
手机发的消息,白嫖桌面端全部保障
手机页面的发送接口不自己实现投递,直接把消息塞进桌面端同一条发送通道:
手机浏览器 → 本机 Web 服务 → 桌面端投递链 → 直连 / 降级 / 中继 / 离线暂存。
这意味着手机发出的消息自动享有桌面端的全部可靠性机制:跨子网中继、防火墙降级、对方离线暂存重投。
Web 端是桌面端的遥控器,不是一套平行系统。这也是它整个只用了九百行代码的原因——每一处"复用现有通道"的决定,都在给未来的自己减负。
文件传输的不对称设计
上传不设大小上限:边收边流式写盘,内存占用恒定——手机拍二十分钟 4K 录像也能传。上传完成直接进桌面端文件面板,记录来源标着"手机"。
下载设了 512MB 上限:因为当前实现把下载响应整个装进内存,超大文件会把内存翻倍。超了就提示"请用桌面端"——承认实现边界,比假装没有边界体面。
前端防呆:最坑的失败是"看起来成功了"
两个小细节值得所有做移动端的同学注意:
聊天记录只保留最近 500 条。页面挂一整天,DOM 不会无限膨胀爆内存。
发送必须拿到服务器确认才渲染气泡。网络抖一下,请求失败了,但前端如果乐观地先把气泡画上去——用户以为发出去了,对端永远收不到。
"看起来成功了"比"发不了"恶劣得多。发不了用户会重试,看起来成功用户连重试的机会都没有。
测试怎么打穿
起真实服务、用真实 HTTP 客户端打全链路:无令牌和错令牌必须 401;中文文件名上传下载完整往返("照片.txt"的编码往返);目录穿越攻击实测——下载和上传的路径穿越都必须被拒;长轮询的挂起语义也有验证。
网页断点、深色模式路径这些"改了容易忘"的常量,全部用契约测试钉死——曾经调试时手滑改过一次断点,从此上了测试。
复盘
移动端最好的分发是没有分发。 浏览器是唯一预装率百分之百的"App";免安装顺带免更新——上一篇自动更新的全部难题,在这条通道上根本不存在。 内网不等于可信网络。 令牌每次重生、文件名单元化、大小上限、并发上限——四个默认值都不影响正常使用,但每一个都在堵一条真实的滥用路径。 实时推送按"改造成本 × 效果"选型。 长轮询和 WebSocket 在"秒级到达"上没有差别,成本是零对架构大改。 别做平行系统。 复用桌面端的投递通道、设计令牌、文件面板——所以它九百行就站稳了。
项目开源在 Gitee:Rust 写的局域网 IM,单二进制免安装,支持飞鸽协议互通、跨子网自动发现、微信式文件传输。
项目地址(复制到浏览器打开):
https://gitee.com/zhongyifeng-git-reporter/local-network-chat-tool
经常被"怎么让手机进内网"折磨的同学,点个在看。下一篇聊 LocalSend 互通:手机上已有的传文件 App,怎么直接和内网 IM 对上话。















































































