workerman 通过监听 http://[::]:8080 可启用 ipv4/ipv6 双栈,需系统支持且 ipv6_v6only=0;错误写法如 0.0.0.0:8080 或 :::8080 会导致单栈或解析失败;客户端连 ipv6 需显式传带方括号地址,dns 解析 aaaa 记录需手动处理。

Workerman 原生支持 IPv6,但默认不启用双栈监听——它不会自动让一个 socket 同时处理 IPv4 和 IPv6 连接,除非你显式配置为 [::] 并确认系统和内核支持双栈模式。
监听 [::] 是同时支持 IPv4/IPv6 的最简方式
Workerman 的协议 URL 支持 IPv6 地址字面量写法。把监听地址从 '0.0.0.0:8080' 换成 'http://[::]:8080',就能让服务在 Linux/macOS(内核 ≥2.6.25)或 Windows Vista+ 上启用双栈 socket(即一个 socket 接收 IPv4 和 IPv6 流量)。
前提是:IPV6_V6ONLY 套接字选项必须设为 0(Workerman 底层已自动处理),否则 [::] 只监听 IPv6。
- 正确写法:
new Worker('http://[::]:8080')、new Gateway('websocket://[::]:8081') - 错误写法:
new Worker('http://0.0.0.0:8080')(仅 IPv4)、new Worker('http://:::8080')(缺方括号,解析失败) - 启动后用
netstat -tlnp | grep :8080或ss -tlnp | grep :8080确认监听行含*:8080或:::8080,而非仅127.0.0.1:8080
为什么 [::] 有时只响应 IPv6?
常见原因是系统级限制:Linux 默认允许双栈,但某些容器环境(如 Docker 默认 bridge 网络)或精简版内核可能禁用 IPv6;Windows 若未启用 IPv6 协议栈,[::] 会静默退化为 IPv4-only。
- 检查 IPv6 是否启用:
cat /proc/sys/net/ipv6/conf/all/disable_ipv6,值为 0 才正常 - Docker 中需加
--sysctl net.ipv6.conf.all.disable_ipv6=0启动容器 - 防火墙常忽略 IPv6 规则:
ip6tables -L看是否放行目标端口,ufw需单独启用ufw enable ipv6 - 客户端连
[::1]失败?先确认ping6 ::1或curl -g http://[::1]:8080能通,排除本地栈问题
Workerman 客户端连接 IPv6 服务要注意什么?
Workerman 的 AsyncTcpConnection 支持 IPv6,但不自动解析 AAAA 记录——若你传域名(如 'tcp://example.com:8080'),它只查 A 记录(IPv4),不会 fallback 到 IPv6。
- 想强制走 IPv6:直接传带方括号的地址,如
new AsyncTcpConnection('tcp://[2001:db8::1]:8080') - 域名需双栈支持?提前用
gethostbyname('example.com')不行,改用dns_get_record('example.com', DNS_AAAA)获取 IPv6 地址再拼接 -
onError必须设:IPv6 DNS 解析失败(如无 AAAA 记录)时不会抛异常,而是触发onError回调,不设就静默失败 - 服务端若只监听
0.0.0.0,IPv6 客户端可能连上但看到源地址是::ffff:192.168.1.100(IPv4 映射地址),行为不可靠,应统一用[::]
真正容易被忽略的是:Workerman 日志里看不到「双栈已启用」这类提示,它只默默按 socket 行为工作;你得靠 ss 或抓包确认流量实际走的是哪一层。别只看 PHP 代码写了 [::] 就以为万事大吉。











