You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP中快速获取本地服务器的公网IP?

快速获取服务器公网IP的可行方案

核心结论

本地直接获取路由器后方服务器的公网IP没有通用方案(除非你的路由器提供API接口,或者服务器本身有绑定公网的网卡),但通过优化远程请求+缓存策略,完全可以把耗时稳定控制在35ms以内,甚至更低。


一、极致优化的远程请求方案

1. 搭建专属的极简IP查询服务

第三方公共IP服务慢的核心原因是:跨网络传输、冗余内容(JSON/HTML)、服务负载高。最快的方式是在同机房/同区域的另一台服务器上搭一个仅返回纯IP字符串的接口:

// 同机房服务器上的ip.php
<?php
echo $_SERVER['REMOTE_ADDR'];
exit;
?>

这个接口没有任何多余内容,传输数据量仅几字节,能大幅降低传输耗时。

2. 极致优化CURL参数

针对上述专属接口,用以下参数配置CURL,把请求开销压到最低:

function get_public_ip() {
    $ch = curl_init('http://同机房服务器IP/ip.php');
    // 核心优化参数
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 30); // 连接超时30ms
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100); // 总超时100ms
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // 禁止重定向
    curl_setopt($ch, CURLOPT_NOSIGNAL, true); // Linux下避免信号干扰
    curl_setopt($ch, CURLOPT_TCP_NODELAY, true); // 禁用Nagle算法,减少延迟
    curl_setopt($ch, CURLOPT_FORBID_REUSE, false); // 允许复用TCP连接
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // 优先用HTTP/1.1
    // 若服务器支持HTTP/2,可改用CURL_HTTP_VERSION_2_0进一步提速
    $ip = curl_exec($ch);
    curl_close($ch);
    return trim($ip);
}

同机房的TCP请求延迟通常在10-20ms左右,加上请求处理时间,完全能满足35ms以内的要求。

3. 缓存策略(关键)

公网IP不会频繁变动,把获取到的IP缓存到本地文件或内存缓存(比如Redis),比如缓存1小时:

function get_cached_public_ip() {
    $cache_file = '/tmp/server_ip.cache';
    $cache_ttl = 3600; // 1小时缓存
    
    // 检查缓存是否有效
    if (file_exists($cache_file) && time() - filemtime($cache_file) < $cache_ttl) {
        return file_get_contents($cache_file);
    }
    
    // 缓存失效,重新获取
    $ip = get_public_ip();
    if ($ip) {
        file_put_contents($cache_file, $ip);
    }
    return $ip;
}

缓存生效时,读取耗时仅几毫秒,完全达标。


二、更快的UDP请求方案

UDP不需要TCP的三次握手,延迟比TCP更低,适合追求极致速度的场景。

1. 搭建UDP IP服务(同机房)

// UDP服务器端(运行在同机房服务器)
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($socket, '0.0.0.0', 12345);
while (true) {
    // 接收客户端请求(无需处理内容)
    socket_recvfrom($socket, $data, 1024, 0, $client_ip, $client_port);
    // 直接返回客户端IP
    socket_sendto($socket, $client_ip, strlen($client_ip), 0, $client_ip, $client_port);
}

2. 客户端请求代码

function get_public_ip_udp() {
    $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 0, 'usec' => 50000]); // 50ms超时
    // 发送空请求
    socket_sendto($socket, '', 0, 0, '同机房UDP服务器IP', 12345);
    // 接收返回的IP
    $result = socket_recvfrom($socket, $ip, 15, 0, $server_ip, $server_port);
    socket_close($socket);
    return $result ? trim($ip) : false;
}

同机房的UDP请求延迟通常在5-15ms,加上缓存,能轻松满足你的速度要求。


三、关于模拟浏览器iframe的思路

浏览器加载iframe快是因为浏览器自带连接池、缓存机制,且是异步加载,但在PHP端模拟这个逻辑本质还是HTTP请求,优化后和上述CURL方案效果一致,没有额外优势。


内容的提问来源于stack exchange,提问作者Daniel Bengtsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:02:03