frankenphp本身不监听http/3端口,冲突实际发生在caddy层;http/3由内置caddy通过tcp+udp 443实现,需排查系统服务(如windows http.sys、macos airplay)占用、udp端口未开放及caddyfile未显式启用experimental_http3。

FrankenPHP本身不监听HTTP/3端口,冲突实际发生在Caddy层
FrankenPHP 没有 HTTP/3 实现,它只提供一个标准 HTTP/1.1 或 HTTPS 后端接口(比如 :80 或 :443)。HTTP/3 的 QUIC 协议处理完全由内置 Caddy 完成。所谓“HTTP/3 端口冲突”,本质是 Caddy 尝试在 443(TCP + UDP)上启用 experimental_http3 时被系统或其它服务抢占——尤其是 Windows 的 HTTP.sys、macOS 的 AirPlay 接收器、或 Docker Desktop 的代理服务。
查 443 端口谁在占:Windows 必须用管理员权限 netstat + PowerShell
普通 CMD 查不到系统级绑定,必须以管理员身份运行:
-
netstat -ano | findstr :443→ 看最后一列 PID;若 PID = 4,就是 HTTP.sys,不能taskkill,得进services.msc停W3SVC或Web Deployment Agent Service -
Get-NetTCPConnection -LocalPort 443 | ForEach-Object { Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue | Select-Object Name, Id, Path }→ 一条命令直接出进程名+路径,避免误判svchost.exe或php.exe是哪个服务 - 如果返回空,不代表安全:HTTP/3 依赖 UDP 443,但
netstat -ano默认不显示 UDP LISTEN,需补查:netstat -ano -p UDP | findstr :443
macOS 上要同时查 TCP 和 UDP,AirPlay 是常见干扰源
macOS 的 lsof 对 UDP 支持有限,单靠 lsof -i :443 很容易漏掉 AirPlay 接收器这类系统服务:
-
lsof -P -n -i :443→ 查 TCP 监听,重点关注COMMAND是否为caddy或kernel_task -
sudo lsof -iUDP -sUDP:LISTEN | grep :443→ 强制查 UDP,AirPlay、ControlCenter 常静默占着:443或:7000 - 若
lsof无输出但 Caddy 启动失败,检查/tmp/frankenphp.sock是否残留——这个 Unix socket 文件冲突会报和端口冲突一模一样的bind: address already in use错误
Caddyfile 配置错误也会“伪装”成端口冲突
即使 443 空闲,Caddy 也可能因配置问题无法启用 HTTP/3,日志里却只报 “failed to start server”,让人误以为是端口问题:
- 必须显式开启:
experimental_http3要写在Caddyfile的全局块或站点块顶部,仅靠tls或reverse_proxy不会自动激活 - 域名必须真实可解析:Caddy 只对公网域名(如
example.com)申请 ACME 证书并启用 HTTP/3;localhost或127.0.0.1永远不会触发experimental_http3 - 别在
Caddyfile里写listen 127.0.0.1:443—— 这会让 Caddy 绑定回环地址,但外部流量进不来,且与 FrankenPHP 的反向代理地址不匹配,导致连接超时而非端口冲突
真正难排查的是 UDP 443 被系统服务静默占用,且错误日志不提示协议类型;查完 TCP 再补 UDP,再核对 Caddyfile 里 experimental_http3 是否生效、域名是否合规,三者缺一不可。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











