Workerman实现局域网文件传输需手动构建TCP服务:监听固定端口(如8000),客户端直连IP;采用带长度头的二进制协议(4字节文件名长+文件名+8字节内容长+分块数据),流式读写避免内存溢出;禁用HTTP/WebSocket以降低开销;客户端须为命令行或桌面程序,不可用浏览器。

Workerman 本身不提供“开箱即用”的局域网文件传输工具,但你可以用它快速搭出一个轻量、可控、支持多客户端的 TCP 文件传输服务——关键不是靠框架内置功能,而是靠你控制协议头、分块读写和连接管理。
怎么让客户端发现并连上你的 Workerman 服务?
局域网传输第一步不是传文件,是让对方知道“你在哪”。Workerman 不做服务发现,所以得自己加一层简易机制:
- 固定监听
0.0.0.0:8000(或任意未被占用的端口),所有局域网设备都能通过http://192.168.x.x:8000或tcp://192.168.x.x:8000直连,前提是防火墙放行该端口 - 不依赖 DNS 或 mDNS,避免增加复杂度;若真需要自动发现,可额外起一个 UDP 广播服务(用
new Worker("udp://0.0.0.0:9999")),但绝大多数局域网场景直接记 IP 更快 - Windows/macOS/Linux 客户端只要能跑 PHP、Python 或有 socket 能力的脚本,就能连——不需要安装额外服务端软件
如何设计一个靠谱的 TCP 文件传输协议?
别用裸 file_get_contents 一把塞,大文件会爆内存、小文件又浪费往返。推荐带长度头的简单二进制协议:
- 前 4 字节为
int32表示后续文件名长度(pack('N', strlen($filename))) - 紧接是文件名 UTF-8 字节流(不含
\0) - 再 8 字节为
int64表示文件内容总长度(pack('J', $size)) - 最后是原始文件二进制数据,分多次
$connection->send()发送,每次最多 64KB - 服务端收到后按此结构解析,用
fopen(..., 'wb')+fwrite流式写入,不落地全量内存
为什么不用 WebSocket 或 HTTP?
因为局域网直传要的是低开销和确定性:
- HTTP 协议头冗余大,上传 10MB 文件可能多发 200KB 无用 header;WebSocket 还要握手、掩码、帧封装,纯增 CPU 开销
- Workerman 的
WorkerTCP 模式是裸 socket,收发就是字节流,你能完全控制 buffer 大小、超时、重试逻辑 - 浏览器无法直接发起任意 TCP 连接(受同源策略限制),所以客户端必须是命令行工具或桌面程序——这反而是优势:可做进度条、断点续传、校验和
- 如果硬要用 HTTP,
onMessage里解析POSTbody 很麻烦,还容易被 Nginx/Apache 拦截或超时,不如绕开
实际运行时最容易忽略的三个点
不是代码写不出来,而是部署时卡在这三处:
- PHP 配置里
max_execution_time和memory_limit对长连接无效,但post_max_size和upload_max_filesize在 HTTP 场景下才起作用——TCP 模式下这些全不生效,你只用管好自己的set_time_limit(0)和流式写入 - Linux 下默认
net.ipv4.ip_local_port_range可能导致大量短连接耗尽端口,但局域网文件传输多为长连接,影响不大;真正要调的是net.core.somaxconn(连接队列长度)和fs.file-max(文件描述符上限) - Windows 客户端用
telnet测试只能发文本,无法传二进制——必须用 Python/PHP/Go 写个最小客户端,哪怕只有 20 行代码,否则永远不知道协议是不是真通


















