workerman监听端口失败时客户端报connection refused或timeout,根本原因是服务未在目标地址端口真正监听:执行ss -tuln | grep :端口,无输出说明未监听成功,仅127.0.0.1:端口表示只响应本机,需改为0.0.0.0:端口并完整重启;ps aux须见worker process,否则onworkerstart有未捕获异常;还需排查端口占用、低权限端口绑定限制及防火墙/安全组拦截。

Workerman监听端口失败时,客户端连接直接报Connection refused或timeout,根本收不到任何握手响应——这不是代码逻辑问题,而是服务压根没在目标地址和端口上真正挂起监听。
确认Workerman进程是否真正在监听端口
很多人看到php start.php start输出“Start success”就以为万事大吉,其实master进程可能启动了,worker子进程却因异常静默退出。必须绕过日志,直查操作系统级监听状态。
执行ss -tuln | grep :5678(把5678换成你实际端口):
若无任何输出 → Workerman根本没监听成功;
若只看到127.0.0.1:5678 → 外部设备连不上,因为只绑定了回环地址;
若看到*:5678或0.0.0.0:5678 → 监听生效,问题出在防火墙或网络路径。
同时运行ps aux | grep WorkerMan:必须看到至少一个WorkerMan: worker process,只有master process说明onWorkerStart里抛了未捕获异常,立刻去workerman.log末尾搜Fatal error或Exception。
检查监听地址是否写死为127.0.0.1
这是最常见也最致命的配置错误。只要监听地址含127.0.0.1,硬件设备(ESP32/STM32)、局域网PC、云上客户端全部无法建立TCP连接——内核直接丢包,连SYN都不响应。
方法一:修改Worker实例初始化代码
$worker = new Worker('tcp://0.0.0.0:5678');
$gateway = new Gateway('websocket://0.0.0.0:2346');
方法二:用通配符写法(效果等同)
$worker = new Worker('tcp://*:5678');
【改完必须完整重启,不能只reload】执行php start.php stop && php start.php start,再跑一遍ss -tuln | grep :5678验证输出是否变成0.0.0.0:5678。
Docker环境同理:容器内代码也得监听0.0.0.0,光靠-p 5678:5678无效。
排查端口占用与权限冲突
第一步:检查端口是否被其他进程霸占
运行lsof -i :5678(macOS/Linux)或netstat -ano | findstr :5678(Windows),若有PID输出,用kill -9 PID或任务管理器结束进程。
第二步:确认端口号是否低于1024
Linux下监听1–1023端口必须用root权限启动,否则bind失败且不报错。直接换端口更安全:5678、2346、9501都是常用非特权端口。
第三步:验证PHP环境是否缺失pcntl扩展
Windows下若用workerman/workerman-for-win,务必删掉同目录下的workerman/workerman包,否则会加载原版Linux扩展导致Call to undefined function pcntl_signal()致命错误。
验证防火墙与安全组是否放行
本地telnet 127.0.0.1 5678通 ≠ 客户端能连——loopback流量不经过防火墙和云安全组。
① 在客户端机器上执行telnet your-server-ip 5678,这是唯一可信的连通性测试。
② 云服务器(阿里云/腾讯云)必须进控制台「安全组」,添加入方向TCP规则,源IP暂时设为0.0.0.0/0测试。
③ Linux服务器执行sudo firewall-cmd --list-ports查当前开放端口,临时加端口命令:sudo firewall-cmd --add-port=5678/tcp --permanent && sudo firewall-cmd --reload。
④ WSL/VirtualBox/宿主机跑Docker时,Windows Defender防火墙或macOS系统防火墙常默认拦截外来连接,必须手动放行或临时关闭。











