如何使用fsockopen检测网络状态且避免脚本因错误终止?
解决fsockopen导致脚本终止的网络检测问题
你的核心问题是未设置超时时间,导致网络断开时fsockopen会长时间阻塞等待,最终触发脚本执行超时终止;虽然用了@抑制错误,但无法解决阻塞超时的本质问题。以下是具体修复方案:
方案1:给fsockopen添加超时参数
修改fsockopen调用,明确设置短超时(比如2秒),避免脚本因长时间等待而终止:
function checkNetwork($domain) { $starttime = microtime(true); $timeout = 2; // 设置2秒连接超时 // 增加errno、errstr参数,便于排查错误(可选) $file = @fsockopen($domain, 80, $errno, $errstr, $timeout); $stoptime = microtime(true); $status = 0; if (is_resource($file)) { fclose($file); $status = floor(($stoptime - $starttime) * 1000); } else { $status = -1; // 网络不通或连接失败 } return $status; }
方案2:改用更可靠的stream_socket_client
stream_socket_client比fsockopen更灵活,支持更精细的超时配置,错误处理也更完善:
function checkNetwork($domain) { $starttime = microtime(true); $timeout = 2; // 创建上下文,设置连接和读取超时 $context = stream_context_create([ 'socket' => [ 'connect_timeout' => $timeout, 'timeout' => $timeout, ] ]); $file = @stream_socket_client("$domain:80", $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context); $stoptime = microtime(true); $status = -1; if (is_resource($file)) { fclose($file); $status = floor(($stoptime - $starttime) * 1000); } return $status; }
方案3:使用curl(推荐)
如果服务器允许使用curl,这是最可靠的方案,curl对网络异常的处理更稳定,且不易被环境限制:
function checkNetwork($domain) { $starttime = microtime(true); $ch = curl_init(); // 只请求头部,减少数据传输 curl_setopt($ch, CURLOPT_URL, "http://$domain"); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 处理跳转(可选) $result = curl_exec($ch); $stoptime = microtime(true); $status = -1; if ($result !== false) { $status = floor(($stoptime - $starttime) * 1000); } curl_close($ch); return $status; }
额外注意事项
- 确保PHP的
max_execution_time设置合理(至少大于你的超时时间),避免脚本本身被强制终止。 - 如果服务器禁用了fsockopen或stream_socket_client,优先选择curl方案。
- 可以将检测目标改为更稳定的公共IP(比如8.8.8.8),减少域名解析带来的额外问题。
内容的提问来源于stack exchange,提问作者Paul Godard
相关产品推荐
相关产品推荐

