phpenv本身不支持websocket服务,因其仅集成apache/nginx+php(cgi/fastcgi模式),无长连接、异步i/o和协程能力;需通过workerman或swoole在命令行单独启动服务,并放行对应端口。

phpEnv 本身不支持 WebSocket 长连接 —— 它只是一个 Windows 下的 PHP 集成环境(类似 XAMPP),默认只带 Apache/Nginx + PHP,没有内置 WebSocket 服务运行时、事件循环或协程能力。 想靠 phpEnv 点点鼠标就跑起 WebSocket 服务,行不通。
为什么 phpEnv 启动不了 WebSocket 服务
WebSocket 服务端需要长期驻留、异步 I/O、处理并发连接,而 phpEnv 中的 PHP 是以 CGI/FastCGI 模式运行在 Apache 或 Nginx 下的,每次请求结束进程即销毁 —— stream_socket_server()、socket_accept() 这类阻塞式套接字操作会立刻退出,根本无法维持连接。
常见错误现象:
- 运行
php websocket_server.php后窗口一闪而过,无任何输出 - 浏览器用
new WebSocket("ws://127.0.0.1:8080")连接,报net::ERR_CONNECTION_REFUSED - 用
telnet 127.0.0.1 8080测试失败,说明端口根本没监听
phpEnv 环境下能走通的 WebSocket 方案
必须绕过 phpEnv 的 Web 服务器层,单独启动一个 PHP 进程作为 WebSocket 服务,并确保它能被外部访问。可行路径只有两条:
- 用
Workerman:纯 PHP 实现,不依赖扩展,兼容 phpEnv 自带的 PHP 版本(PHP 7.2+ 即可);需在命令行中手动启动,不能通过 phpEnv 控制面板管理 - 用
Swoole:性能更好,但 phpEnv 默认不带 Swoole 扩展;需手动下载对应 PHP 版本的php_swoole.dll,放进php/ext/并在php.ini中启用extension=php_swoole.dll,再 CLI 启动
注意:无论哪种,都必须用命令行执行(如 php start.php),且该进程要一直运行 —— phpEnv 的「服务管理」里看不到它,也不能用「重启 Apache」来重启它。
Workerman 在 phpEnv 中的实际配置步骤
这是最轻量、成功率最高的方案,无需编译、不改 phpEnv 核心配置:
- 在 phpEnv 的网站根目录(如
D:\phpEnv\www\websocket)下执行:composer require workerman/workerman - 新建
start.php,内容为:
require 'vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker('websocket://0.0.0.0:9501');
$worker->onMessage = function($connection, $data) {
$connection->send('收到:' . $data);
};
Worker::runAll();
- 打开 Windows 命令提示符(CMD),cd 到该目录,执行:
php start.php start(加start参数才能后台运行;不加则前台阻塞,关窗口即退出) - 检查是否监听成功:
netstat -ano | findstr :9501,应看到LISTENING状态及对应 PID - 前端测试:
new WebSocket("ws://127.0.0.1:9501")—— 注意不是http://,也不是 phpEnv 的 Apache 端口(如 8080)
防火墙与端口访问常被忽略的关键点
即使服务跑起来了,Windows 防火墙默认会拦截非 80/443 的入站连接,导致局域网其他设备连不上你的 ws 服务:
- 必须手动放行端口(如 9501):控制面板 → Windows Defender 防火墙 → 高级设置 → 入站规则 → 新建规则 → 端口 → TCP → 特定本地端口 9501 → 允许连接
- phpEnv 的 Apache 和 WebSocket 服务是两个独立进程,共用 80 端口会冲突;务必让 WebSocket 服务监听其他端口(如 9501、6161),并在前端 URL 显式写出
- 如果想用域名或
wss,必须配 Nginx 反向代理(phpEnv 自带 Nginx 可启用),并配置proxy_set_header Upgrade $http_upgrade等关键头,否则握手直接失败
真正卡住人的往往不是代码,而是 Windows 防火墙静默丢包、端口被占用、或误以为「phpEnv 启动了 Apache 就等于 WebSocket 也启动了」—— 它俩根本不在一个世界里。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











