Workerman接收不到数据需三路并行验证:①用ss -tuln确认监听0.0.0.0:端口而非127.0.0.1;②ps aux查master与worker进程是否均存在;③客户端telnet服务器真实IP,排除安全组、防火墙、Docker绑定问题。

Workerman接收不到数据时,不能只盯着onMessage回调里有没有打印日志,必须从网络层、协议层、进程状态三路并行验证——漏掉任何一层都可能让你在错误方向上浪费数小时。
确认内核是否真在监听目标端口
执行ss -tuln | grep :你的端口(例如ss -tuln | grep :2345),看到*:2345或0.0.0.0:2345才算真正对外暴露;如果只显示127.0.0.1:2345,说明Workerman绑定的是回环地址,外部设备发包过来内核直接丢弃。
【必须完整重启服务】改完监听地址后,不能只reload,要执行php start.php stop && php start.php start,否则旧配置仍驻留在内存中。
再运行ps aux | grep WorkerMan,确保输出里同时存在master process和至少一个worker process;若只有master没有worker,大概率是onWorkerStart里抛了未捕获异常,立刻去workerman.log末尾搜Fatal error或Exception。
验证客户端真实连接路径是否通
在客户端机器(比如ESP32开发板、另一台Linux服务器)上直接执行:telnet 你的服务器公网IP 2345,不是在Workerman本机上telnet 127.0.0.1。
如果这步不通,立即检查三层拦截:云厂商安全组(阿里云/腾讯云控制台→安全组→入方向添加TCP规则,源IP暂设0.0.0.0/0)、宿主机防火墙(CentOS用firewall-cmd --add-port=2345/tcp --permanent && firewall-cmd --reload)、Docker容器是否也监听0.0.0.0:2345而非127.0.0.1:2345。
Windows/macOS下跑WSL或VirtualBox时,宿主机系统防火墙默认会拦外来连接,临时关闭或加例外规则比反复调试代码更高效。
区分协议类型再查收据逻辑
方法一:你用的是纯TCP协议
客户端发来的就是原始字节流,onMessage收到的$data就是裸数据。此时不存在$_POST,也不需要解析HTTP头——如果你在onMessage里写print_r($_POST)还指望有输出,那永远看不到数据。
方法二:你启的是HTTP协议(new Worker('http://0.0.0.0:2346'))onMessage参数是Workerman\Protocols\Http\Request对象,必须调用$request->post()或$request->rawBody()取值。$_POST在Workerman里永远为空,这是设计使然,不是bug。
注意:用$request->post()前提是客户端发的是application/x-www-form-urlencoded或multipart/form-data;如果是JSON请求,Content-Type为application/json,就必须用$request->rawBody()再手动json_decode(),否则拿不到任何字段。
检查TIME_WAIT堆积与连接复用问题
第一步:执行netstat -an | grep :2345 | grep TIME_WAIT | wc -l,如果返回值超过5000,说明短连接频繁释放导致端口资源被占满,新连接bind失败但Workerman不报错。
第二步:在Worker构造后、Worker::runAll()前加入:Worker::$maxConnection = 10000; 和 Worker::$reusePort = true;,缓解单端口压力。
第三步:确认客户端是否用了长连接。如果客户端每次发完数据就断开,而服务端又没做连接保活,大量TIME_WAIT会迅速堆积——这时应让客户端复用连接,或服务端启用$connection->close()显式清理。

















