Swoole的WSS需同时满足三个硬条件:启用SWOOLE_SSL标志、编译时支持OpenSSL、证书路径正确且可读;任一缺失均导致客户端连接失败或握手卡住。

直接上结论:Swoole 的 WSS 不是“开个开关”,而是必须满足三个硬条件——SWOOLE_SSL 标志启用、OpenSSL 编译支持、证书路径正确且可读。漏掉任一环,new swoole_websocket_server 启动时不会报错,但客户端连 wss:// 会直接失败或握手卡住。
为什么 new swoole_websocket_server(..., SWOOLE_SOCK_TCP | SWOOLE_SSL) 启动没报错却连不上
这是最常被忽略的底层依赖问题。Swoole 的 SSL 支持不是运行时加载的扩展,而是在编译阶段决定的:
-
SWOOLE_SSL只是告诉 Swoole “我要走 TLS”,但若 PHP 扩展本身没带 OpenSSL 支持,它就只是个无效标志 - 用宝塔面板安装的 Swoole 默认可能不带
--enable-openssl,尤其老版本或一键安装包 - 验证方式不是看
php --ri swoole里有没有 ssl 字样,而是执行:php -r "echo swoole_version();"后再运行:php -r "var_dump(extension_loaded('openssl'));"——两个都得是true - 如果 OpenSSL 扩展已加载但 Swoole 仍不认 SSL,说明 Swoole 编译时没链接 OpenSSL 库,必须重装 Swoole(宝塔里卸载再手动编译,加
--enable-openssl)
swoole_websocket_server 的 ssl_cert_file 和 ssl_key_file 怎么填才有效
路径和格式错误是静默失败的主因,不是权限问题就是文件类型不对:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
-
ssl_cert_file必须是完整证书链(fullchain.pem),不是单独的cert.pem;否则 iOS/Safari/部分 Android 客户端握手失败 -
ssl_key_file必须是未加密的私钥(即打开文件看不到-----BEGIN ENCRYPTED PRIVATE KEY-----);如果用了openssl pkcs8 -topk8 -nocrypt转换过,才算合格 - 路径推荐绝对路径,避免相对路径在守护进程模式下解析错位;例如:
/etc/letsencrypt/live/example.com/fullchain.pem - PHP 进程用户(通常是
www或nobody)必须有该路径下所有父目录的x权限,否则open()系统调用失败,但 Swoole 不抛异常,只拒绝连接
Nginx 反向代理 wss 到 swoole 时 Upgrade 头总被丢掉
这不是 Swoole 配置问题,而是 Nginx 代理层没通过 WebSocket 协议升级检查,浏览器会直接返回 400 或断开:
- 必须同时设置:
proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection "upgrade";——少一个都不行 -
proxy_http_version 1.1是强制项,HTTP/1.0 不支持 upgrade 机制 - 不要用
location /wss { ... }这种路径前缀做代理;WSS 握手请求是GET /,路径匹配必须是location / { ... }或至少location = / -
proxy_read_timeout建议设为3600(1小时),否则空闲连接会被 Nginx 主动断开,表现就是“连着连着就断了”
客户端 new WebSocket('wss://...') 报错 ERR_CONNECTION_CLOSED 怎么定位
这个错误表面是网络层断开,实际原因集中在服务端证书和域名一致性上:
- 检查浏览器地址栏是否显示锁图标并点开证书信息——域名是否完全匹配(
example.com≠www.example.com),通配符证书是否覆盖子域 - 用命令行验证证书链是否完整:
openssl s_client -connect example.com:9501 -servername example.com(注意端口是 Swoole 监听端,非 443);如果返回Verify return code: 0 (ok)才算可信 - 如果用的是自签名证书或内网 CA,浏览器一定拒绝,WSS 不接受任何例外;生产环境必须用 Let's Encrypt 或商业 CA 签发的证书
- 别在开发时用 IP 地址访问
wss://192.168.x.x:9501——证书里没有 IP Subject Alternative Name,现代浏览器直接拦截
真正麻烦的从来不是代码怎么写,而是证书链是否完整、OpenSSL 是否真被 Swoole 链接、Nginx 是否把 Upgrade 头原样透传——这三个点任何一个断掉,WSS 就只剩黑盒失败。

















