
本文旨在解决php脚本在循环检查多个远程文件链接时遇到的`err_connection_reset`问题。通过分析传统`get_headers`方法的局限性,我们提出并详细演示了如何利用php的curl多请求功能(`curl_multi_*`)实现高效、并行且健壮的链接状态检查,从而避免连接重置错误,并显著提升脚本性能。
在开发PHP脚本以检查远程服务器上文件的存在性时,开发者常会遇到一个常见但棘手的问题:当脚本尝试连续检查大量URL时,可能会收到ERR_CONNECTION_RESET错误,甚至导致后续无法通过浏览器访问这些链接。即使引入sleep()函数进行延迟,也往往无法彻底解决问题。这通常是由于服务器端的连接限制、防火墙规则或客户端在短时间内发起了过多同步请求,导致服务器主动断开连接。
原始问题中使用的get_headers()函数,虽然在检查单个URL时非常方便,但其本质是一个同步阻塞操作。这意味着每次请求都会等待服务器响应,然后才能发起下一个请求。当脚本在短时间内对同一服务器发起大量此类请求时,可能会触发以下问题:
为了克服get_headers()的局限性,PHP的cURL扩展提供了一套强大的多请求(curl_multi_*)API,允许开发者并行处理多个HTTP请求。这种方式具有以下显著优势:
使用cURL多请求处理多个URL的基本步骤如下:
立即学习“PHP免费学习笔记(深入)”;
以下是使用cURL多请求并行检查多个文件URL的示例代码:
<?php
function checkAllUrls() {
$revisionNumber = 25;
$minorNumber = 2;
$buildNumber = 128;
// 初始化cURL多请求句柄
$multiCurl = curl_multi_init();
$curlHandles = []; // 用于存储每个cURL句柄及其关联信息
// 循环构建URL并创建单个cURL句柄
for ($x = $buildNumber; $x > 0; $x--) {
// 构建文件URL
$combinedUrl = 'http://update.example.com/Files/Updates/6.' . $revisionNumber . '.' . $minorNumber . '.' . $x . '/application7_' . $revisionNumber . '_' . $minorNumber . '_' . $x . '_de_FullInstallerx64.exe';
// 初始化单个cURL句柄
$curl = curl_init();
// 设置URL
curl_setopt($curl, CURLOPT_URL, $combinedUrl);
// 获取文件时间(可选)
curl_setopt($curl, CURLOPT_FILETIME, true);
// 只发送HEAD请求,不下载内容,高效检查文件存在性
curl_setopt($curl, CURLOPT_NOBODY, true);
// 将响应作为字符串返回,而不是直接输出
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// 包含响应头信息
curl_setopt($curl, CURLOPT_HEADER, true);
// 设置连接超时和请求超时,防止长时间等待
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); // 连接超时5秒
curl_setopt($curl, CURLOPT_TIMEOUT, 10); // 总请求超时10秒
// 将单个cURL句柄添加到多请求句柄中
curl_multi_add_handle($multiCurl, $curl);
// 存储句柄及其关联的build号,以便后续处理
$curlHandles[] = ['curl' => $curl, 'build' => $x];
}
// 执行所有cURL请求直到完成
$stillRunning = null;
do {
// 循环执行cURL请求,直到所有请求都处理完毕
// curl_multi_exec是非阻塞的,会处理所有可用的请求
$mrc = curl_multi_exec($multiCurl, $stillRunning);
} while ($stillRunning > 0 && $mrc == CURLM_OK); // 确保没有错误发生
// 遍历所有句柄,处理请求结果
foreach ($curlHandles as $item) {
$curl = $item['curl'];
$build = $item['build'];
file_put_contents('log.txt', "Checking Build: " . $build . "\n", FILE_APPEND);
// 获取HTTP状态码
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// 获取实际请求的URL
$effectiveUrl = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
if ($httpCode === 404) {
// HTTP 404 Not Found 表示文件不存在
$exists = "no";
file_put_contents('log.txt', $effectiveUrl . " - " . "does not exist. \n", FILE_APPEND);
} else if ($httpCode >= 200 && $httpCode < 300) {
// HTTP 2xx 状态码表示请求成功,文件存在
$exists = "yes";
file_put_contents('log.txt', $effectiveUrl . " - " . "exists. \n", FILE_APPEND);
} else {
// 其他状态码,例如 5xx 服务器错误,或者连接失败等
$exists = "unknown";
file_put_contents('log.txt', $effectiveUrl . " - " . "status: " . $httpCode . " (could not verify existence). \n", FILE_APPEND);
}
// 从多请求句柄中移除当前cURL句柄并关闭它
curl_multi_remove_handle($multiCurl, $curl);
curl_close($curl); // 显式关闭单个cURL句柄
}
// 关闭cURL多请求句柄
curl_multi_close($multiCurl);
}
// 调用函数执行检查
// checkAllUrls(); // 在实际应用中调用此函数当PHP脚本需要高效、健壮地检查大量远程链接时,get_headers()等同步方法因其效率低下和容易触发服务器端限制而不再适用。通过采用PHP的cURL多请求机制,开发者可以实现请求的并行处理,显著提升脚本性能,有效避免ERR_CONNECTION_RESET等连接问题,并对请求过程拥有更细粒度的控制。理解并正确运用curl_multi_*函数是构建高性能网络请求处理脚本的关键。
以上就是PHP中高效并行检查多链接状态的教程的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号