必须用SWOOLE_SOCK_UNIX_STREAM(或SWOOLE_SOCK_UNIX_DGRAM)才能启用Unix域套接字;若误用SWOOLE_SOCK_TCP,即使绑定localhost或127.0.0.1,仍走TCP/IP协议栈,无法享受VFS层零拷贝、低延迟和文件系统权限控制优势。

UnixSocket 用 SWOOLE_SOCK_UNIX_STREAM 还是 SWOOLE_SOCK_TCP?
必须用 SWOOLE_SOCK_UNIX_STREAM(或 SWOOLE_SOCK_UNIX_DGRAM)才能走 Unix 域套接字;用 SWOOLE_SOCK_TCP 即使绑 127.0.0.1 或 localhost,也仍是 TCP/IP 协议栈路径。Swoole 不会自动把 TCP 配置“降级”为 Unix Socket——这是两个完全独立的 socket domain,内核层面不互通。
常见错误是误以为 $server = new Swoole\Server('localhost', 8080, SWOOLE_PROCESS, SWOOLE_SOCK_TCP) 能复用 Unix 套接字语义,实际它仍走 loopback 网络栈,有额外开销且不享受文件系统权限控制。
bind() 路径和权限问题怎么处理?
Unix Socket 在文件系统中创建一个真实路径(如 /tmp/swoole.sock),这个文件由 Swoole 主进程创建并持有,需注意:
- 启动前确保父目录存在且进程有写权限,否则
bind()失败报Permission denied或No such file or directory - 旧 socket 文件残留会导致
Address already in use—— Swoole 不会自动清理,得手动unlink('/tmp/swoole.sock')或加启动脚本判断 - 客户端连接时路径必须**完全一致**,包括空格和结尾斜杠,
/tmp/swoole.sock和/tmp/swoole.sock/是两个不同路径
为什么用 Unix Socket 比 127.0.0.1:xxx 更快?
本质区别不在“本地”,而在是否绕过网络协议栈:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
-
127.0.0.1:数据仍经 IP 层、ICMP、TCP 状态机、socket 缓冲区拷贝,受 net.ipv4.tcp_* 内核参数影响 - Unix Socket:直接在 VFS(虚拟文件系统)层完成 copy-on-write 数据传递,无校验和、无序列号、无重传逻辑,延迟低 30%~50%
实测在高并发短连接场景(如 PHP-FPM 与后端服务通信),Unix Socket 的 QPS 可比 loopback TCP 高 1.5~2 倍,尤其当 net.core.somaxconn 或 net.ipv4.tcp_max_syn_backlog 成瓶颈时更明显。
客户端连不上 Unix Socket 的典型现象
不是超时,而是直接失败,错误信息往往很短:
-
Connection refused:socket 文件不存在,或服务未启动,或路径写错 -
Permission denied:socket 文件属主/权限不对(如服务以 root 启动,客户端以 www-data 运行但没加 group 权限) -
Operation not permitted:SELinux/AppArmor 限制了 Unix domain socket 创建(常见于 CentOS/RHEL 容器) - PHP 中
swoole_client构造时传SWOOLE_SOCK_UNIX_STREAM但地址写成 IP 格式,会静默 fallback 到 TCP,行为诡异
真正难排查的是权限嵌套:比如 socket 文件属组正确,但父目录 /tmp 的 sticky bit(drwxrwxrwt)被禁用,或容器挂载时用了 noexec 选项导致 bind 失败——这些不会报具体路径问题,只抛通用 errno。

















