fsockopen 无法获取本机 IP,因其仅建立 TCP 连接,不读取网卡配置,stream_socket_get_name 返回的是对端地址而非本机真实 IP。

用 fsockopen 获取本机 IP 不可行 —— 它只能发起 TCP 连接,不提供本机网络接口信息,本质和“通过打电话问自己家住哪”一样荒谬。
为什么 fsockopen 不能用来获取本机 IP
fsockopen 的作用是建立一个到远程(或本地)服务的 socket 连接,比如连 127.0.0.1:80 或 google.com:443。它不读取系统网卡配置、不调用 gethostbyname、也不触发任何地址解析逻辑来反推“本机出口 IP”。
- 即使连接成功,
stream_socket_get_name($fp, true)返回的是对端地址(比如你连的是localhost,就返回127.0.0.1),不是本机真实网卡 IP - 若目标不可达,会抛出警告或返回
false,完全无法用于探测 - 它无法区分
192.168.x.x、10.x.x.x或公网 IP,更不处理多网卡场景
真正可用的 PHP 获取本机 IP 方法
“本机 IP”需先明确定义:是指监听服务的绑定地址?当前默认路由出口 IP?还是某张网卡的 IPv4 地址?不同场景对应不同方案:
- 查当前服务器**绑定在 HTTP 请求中的客户端看到的入口 IP** → 看
$_SERVER['SERVER_ADDR'](仅适用于 Web SAPI,且是 Apache/Nginx 配置的监听地址) - 查**所有本地非回环 IPv4 地址** → 用
net_get_interfaces()(PHP 7.2+),遍历unicast列表并排除127.0.0.1 - 查**默认路由出口的公网/局域网 IP** → 执行系统命令如
ip route | awk '/default/ {print $3}'(Linux)或route print \| findstr "Default Gateway"(Windows),再反向查该网关所在网卡 - 简单但有缺陷的方式:用
gethostbyname(gethostname())—— 可能返回127.0.0.1(如果/etc/hosts把 hostname 指向了 localhost)
常见误用与坑点
很多人试图用 fsockopen('8.8.8.8', 53) 再调 stream_socket_get_name($fp, false) 来“骗出本机出口 IP”,这存在严重问题:
立即学习“PHP免费学习笔记(深入)”;
- 连接
8.8.8.8:53并不保证成功(防火墙、DNS 策略、UDP/TCP 差异),fsockopen默认走 TCP,而 DNS 查询常用 UDP,行为不一致 - 即使连上,
stream_socket_get_name($fp, false)返回的是本地分配的随机源端口绑定的地址,**不一定是主网卡 IP**(尤其在多宿主、Docker、NAT 环境下) - 该方法在 CLI 模式下可能返回
0.0.0.0或空字符串,在某些容器中甚至触发Permission denied - PHP-FPM 下受
disable_functions影响,fsockopen常被禁用,而net_get_interfaces更安全稳定
真要可靠获取本机 IP,优先用 net_get_interfaces() + 过滤逻辑;若需兼容老版本 PHP,再考虑 exec('hostname -I') 或解析 /sbin/ifconfig 输出 —— 但永远别指望 fsockopen 返回你的网卡地址。











