workerman小程序wss连接失败的根源在于监听地址、ssl配置、进程状态、证书链、网络策略及域名合规性六大环节。需确保监听0.0.0.0而非127.0.0.1,显式设置$worker->transport='ssl',使用fullchain.pem并验证证书链完整性,开发环境verify_peer设为false,云安全组放行wss端口,且小程序必须用已备案https二级域名访问。

Workerman已配置好SSL证书并启动wss服务,但小程序或Web客户端仍无法建立连接,表现为WebSocket connection to 'wss://' failed、net::ERR_CONNECTION_REFUSED或握手超时——这说明证书只是基础条件,网络层、协议层、进程层任一环节断裂都会导致推送链路中断。
确认Workerman进程真实监听wss端口
执行 ss -tuln | grep :8443(将8443替换为你实际配置的wss端口),必须看到 *:8443 或 0.0.0.0:8443;若只显示 127.0.0.1:8443,说明Worker绑定的是本地回环地址,外部请求根本进不来。
检查代码中监听地址是否写成 'websocket://127.0.0.1:8443' ——必须改为 'websocket://0.0.0.0:8443',否则即使证书正确也收不到任何wss握手包。
运行 ps aux | grep Worker,确认输出中同时存在 master process 和至少一个 worker process;只有master没有worker,说明onWorkerStart内发生未捕获异常,去 workerman.log 末尾找 Fatal error 或 Exception。
验证SSL上下文配置是否真正生效
方法一:检查$worker->transport是否显式设为'ssl'
仅在构造Worker时传入ssl_context参数还不够。Workerman要求必须手动设置$worker->transport = 'ssl',否则它会忽略ssl_context,退化为普通ws服务——这是最隐蔽的连不上原因,日志里完全不报错。
方法二:确认local_cert路径指向的是fullchain.pem而非cert.pem
【证书链断裂会导致客户端信任失败,微信小程序直接拒绝连接】。用命令 openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout 验证文件是否包含域名证书+中间CA证书;若只有一段BEGIN CERTIFICATE,说明漏了chain部分。
方法三:开发环境必须设'verify_peer' => false
微信开发者工具调试域名是127.0.0.1或localhost,而SSL证书绑定的是正式域名,PHP OpenSSL默认校验CN/SAN字段,设为true必握手失败。生产环境可设为true,但需确保证书SAN包含所有接入域名。
穿透防火墙与云安全组
第一步:从客户端机器直连测试
在小程序所在手机或PC上执行 telnet your-domain.com 8443(非服务器本机)。如果超时或拒绝,问题一定出在网络路径上,不是代码问题。
第二步:检查云厂商安全组规则
阿里云/腾讯云控制台 → 安全组 → 入方向规则 → 添加一条:类型TCP,端口8443,源IP填0.0.0.0/0(临时测试用),协议选TCP。很多开发者只开了80/443,却忘了wss自定义端口要单独放行。
第三步:确认Nginx/Apache未做SSL终结
如果你在Workerman前套了Nginx,且Nginx已配置HTTPS并反代到http://127.0.0.1:2345,那么Workerman必须用ws://协议启动,不能配ssl_context——否则变成wss→https→ws三层嵌套,握手必然失败。此时应关闭Workerman的SSL,让Nginx统一处理加密。
检查客户端连接协议与域名一致性
方法1:小程序代码必须用wss://开头,且域名必须与证书完全匹配
证书是www.example.com签发的,就不能用example.com或api.example.com连接(除非证书含SAN)。微信小程序校验极严,IP地址、localhost、127.0.0.1一律被拒绝,【必须使用已备案且HTTPS有效的二级域名】。
方法2:浏览器F12控制台测试连接
在Chrome中打开开发者工具 → Console,粘贴以下代码并回车:
ws = new WebSocket("wss://your-domain.com:8443"); ws.onerror = e => console.error(e); ws.onopen = () => console.log("open ok");
若控制台报 ERR_SSL_PROTOCOL_ERROR,说明Workerman未正确加载证书或私钥;若报 ERR_CONNECTION_REFUSED,说明端口未通或进程未监听;若长时间无响应,大概率是安全组或防火墙拦截。











