部署远程服务器后Workerman WebSocket连接异常问题求助
Workerman WebSocket部署问题排查
初始问题
用Workerman开发的聊天功能本地运行正常,部署到远程服务器后控制台报错:
"WebSocket is already in CLOSING or CLOSED state"
起初以为是本地用ws://协议、服务器是https://导致的,于是配置了SSL证书(证书为.pem格式,私钥为.key格式),但报错依旧。当前使用PHP CLI 5.4,怀疑是服务器环境问题。
附相关内容截图:
- 报错信息截图
- 前端JS代码截图
- 后端PHP代码截图
- SSL配置截图
更新1:SSL重装后新报错
联系服务商重新安装SSL后,出现新错误:
"SSL handshake error: stream_socket_enable_crypto(): SSL: Success"
更新2:连接建立后立即断开
现在WebSocket连接可以建立,但会立刻断开。
排查与解决方案
1. PHP版本兼容性问题
PHP 5.4过于老旧,存在大量SSL相关Bug,尤其是stream_socket_enable_crypto函数对现代SSL协议(如TLS 1.2+)支持不完善,而Workerman官方推荐PHP7.0及以上版本。优先升级PHP到7.2+版本,这是解决SSL握手问题的核心前提。
2. SSL证书配置验证
- 证书私钥匹配检查:执行以下两个命令,对比输出的MD5值是否一致,不一致则说明证书和私钥不匹配
openssl x509 -noout -modulus -in 你的证书.pem | openssl md5 openssl rsa -noout -modulus -in 你的私钥.key | openssl md5 - 证书链完整性:确保
.pem文件包含完整证书链(根证书+中间证书+域名证书),缺少中间证书会导致握手失败 - 文件权限设置:证书文件权限设为
644,私钥设为600,保证Workerman进程能正常读取
3. Workerman SSL配置正确性
检查Workerman的SSL配置代码,确保格式准确:
$worker = new Worker('websocket://0.0.0.0:8282'); $worker->transport = 'ssl'; $worker->ssl = array( 'local_cert' => '/path/to/你的证书.pem', 'local_pk' => '/path/to/你的私钥.key', 'verify_peer' => false, );
注意:local_cert必须是包含完整证书链的.pem文件,不能仅用单独的域名证书。
4. 端口与防火墙检查
- 确认WebSocket端口(如8282)已在服务器防火墙、云服务商安全组中开放
- 若用Nginx反向代理,需添加WebSocket代理规则,此时前端连接地址应为
wss://你的域名/ws:
location /ws { proxy_pass http://127.0.0.1:8282; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; }
5. 连接断开问题排查
- 开启Workerman日志:添加
$worker->logFile = '/var/log/workerman.log';,查看日志中的断开原因 - 前端连接协议:HTTPS网站必须用
wss://协议,不能用ws://,否则浏览器会拦截 - 服务器时间:时间偏差过大可能导致SSL证书验证失败,执行
date命令确认服务器时间与本地时间一致
内容的提问来源于stack exchange,提问作者Drimgo
相关产品推荐
相关产品推荐

