查端口占用需用netstat或ss按端口筛选,如netstat -tlnp | grep :9502获取pid;杀进程或改端口二选一,优先改非特权端口;so_reuseaddr对swoole无效,须避免误杀进程和重复初始化。

查端口占用:先别改代码,用 netstat 或 ss 看谁在听
报 Address already in use 时,Swoole 根本没机会执行到你的 PHP 逻辑,问题出在系统层面——端口已被别的进程绑定了。Linux 下最直接的办法是查监听状态:
-
netstat -tlnp | grep :9502(把9502换成你实际配的端口)→ 输出里第 7 列类似1234/php,1234就是 PID - 如果提示
netstat: command not found,说明系统精简过,改用ss -tlnp | grep :9502,效果一样 - Windows 用户用
netstat -ano | findstr :9502,再用tasklist | findstr 1234确认进程名
注意:ps aux | grep swoole 容易误杀其他项目的 Swoole 进程,必须按端口查,不能按进程名粗杀。
杀进程还是换端口:看场景选更稳妥的方案
确认是哪个 PID 占了端口后,下一步取决于你能不能动它:
- 如果是上次
Ctrl+C没彻底退出残留的本项目进程 →kill -9 1234干掉,再启动即可 - 如果是 Nginx、Java 服务、另一个 PHP CLI 脚本占了
9501或8324→ 别硬杀,优先改自己项目的端口,比如改成9510或12345 - 端口建议选
1024–49151区间,避开1–1023的特权端口(否则要root权限)
改端口不光是改配置里的数字,还要检查是否多个 Swoole\Server 实例被重复初始化,导致同一端口 bind 两次——这种情况 kill 进程也没用,得修代码。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
为什么加 SO_REUSEADDR 不是万能解
有些资料说在 socket 层加 setsockopt(..., SO_REUSEADDR, ...) 就能绕过冲突,但对 Swoole 来说这基本无效:
- Swoole 是封装好的扩展,不暴露底层 socket fd 给用户,你没法在
bind()前插这段逻辑 - 即使自己写原生 socket,
SO_REUSEADDR解决的是TIME_WAIT状态下的快速复用,不是两个进程抢同一个端口 - 真要用这个选项,得改 Swoole 源码重新编译,成本远高于查 PID 或换端口
所以别在 Swoole 启动脚本里折腾 socket_setopt,它根本不起作用。
验证端口是否真空闲:别信“没输出就完事”
执行 kill -9 1234 后,别急着启动 Swoole,多验一步:
- 再跑一次
netstat -tlnp | grep :9502,确保完全没输出 - 有时候进程被 kill 后子进程还在,或者 systemd 服务自动拉起,可以加
-w参数轮询:watch -n 1 'netstat -tlnp | grep :9502' - 启动失败仍报同样错误?检查是不是配置里写了
127.0.0.1:9502,而占用者是0.0.0.0:9502—— 这俩在系统眼里是同一个端口,照样冲突
真正容易被忽略的是:Swoole 默认监听 0.0.0.0,只要任意网卡上该端口被占,就失败;而你以为只绑本地回环,其实不是。










