curl_pause() 函数用于暂停和恢复cURL连接。这个函数在需要临时停止数据传输(如流量控制、限速等场景)时非常有用。
curl_pause ( CurlHandle $handle , int $flags ) : int
| 参数 | 描述 |
|---|---|
| handle | 由 curl_init() 返回的 cURL 句柄。 |
| flags | 控制暂停行为的标志位(参见下面的选项表)。 |
返回错误代码,成功时返回 CURLE_OK (0)。
| 选项 | 值 | 描述 |
|---|---|---|
CURLPAUSE_RECV |
1 | 暂停数据接收 |
CURLPAUSE_SEND |
4 | 暂停数据发送 |
CURLPAUSE_ALL |
5 | 暂停所有数据传输(接收和发送) |
CURLPAUSE_CONT |
0 | 恢复暂停的数据传输 |
// 初始化cURL会话
$ch = curl_init();
// 设置cURL选项
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/drip?duration=5&numbytes=1000',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_WRITEFUNCTION => function($ch, $data) {
static $total = 0;
$total += strlen($data);
echo "接收到 " . strlen($data) . " 字节数据,总计: {$total} 字节\n";
// 当接收到500字节时暂停接收
if ($total >= 500) {
echo "已达到500字节,暂停接收...\n";
curl_pause($ch, CURLPAUSE_RECV);
// 3秒后恢复接收
echo "等待3秒后恢复...\n";
sleep(3);
curl_pause($ch, CURLPAUSE_CONT);
echo "恢复接收数据\n";
}
return strlen($data);
}
]);
// 执行cURL请求
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL错误: ' . curl_error($ch);
}
curl_close($ch);
class RateLimitedDownload {
private $ch;
private $bytesPerSecond;
private $lastTime;
private $bytesTransferred;
public function __construct($url, $bytesPerSecond = 1024) {
$this->ch = curl_init();
$this->bytesPerSecond = $bytesPerSecond;
$this->lastTime = microtime(true);
$this->bytesTransferred = 0;
curl_setopt_array($this->ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => false,
CURLOPT_WRITEFUNCTION => [$this, 'writeCallback']
]);
}
public function writeCallback($ch, $data) {
$dataLength = strlen($data);
$this->bytesTransferred += $dataLength;
// 计算应该传输的时间
$expectedTime = $this->bytesTransferred / $this->bytesPerSecond;
$actualTime = microtime(true) - $this->lastTime;
// 如果传输太快,暂停一下
if ($actualTime < $expectedTime) {
$sleepTime = ($expectedTime - $actualTime) * 1000000; // 转换为微秒
if ($sleepTime > 10000) { // 至少睡眠10毫秒
curl_pause($this->ch, CURLPAUSE_RECV);
usleep((int)$sleepTime);
curl_pause($this->ch, CURLPAUSE_CONT);
}
}
echo "已下载: {$this->bytesTransferred} 字节, 速率: " .
round($this->bytesTransferred / max($actualTime, 0.001)) . " 字节/秒\n";
return $dataLength;
}
public function download() {
$this->lastTime = microtime(true);
$result = curl_exec($this->ch);
if (curl_errno($this->ch)) {
throw new Exception('下载错误: ' . curl_error($this->ch));
}
return $result;
}
public function __destruct() {
if ($this->ch) {
curl_close($this->ch);
}
}
}
// 使用示例:限制下载速率为10KB/秒
try {
$downloader = new RateLimitedDownload(
'https://httpbin.org/stream-bytes/50000',
10 * 1024 // 10KB/秒
);
$downloader->download();
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
function controlledDownload($url, $controlCallback) {
$ch = curl_init();
$downloadInfo = [
'total_size' => 0,
'chunk_count' => 0,
'start_time' => microtime(true)
];
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => false,
CURLOPT_WRITEFUNCTION => function($ch, $data) use (&$downloadInfo, $controlCallback) {
$chunkSize = strlen($data);
$downloadInfo['total_size'] += $chunkSize;
$downloadInfo['chunk_count']++;
// 调用控制回调函数决定是否暂停
$action = $controlCallback($downloadInfo, $chunkSize);
if ($action === 'pause_recv') {
curl_pause($ch, CURLPAUSE_RECV);
// 模拟处理时间
usleep(100000); // 100毫秒
curl_pause($ch, CURLPAUSE_CONT);
} elseif ($action === 'pause_all') {
curl_pause($ch, CURLPAUSE_ALL);
sleep(1); // 暂停1秒
curl_pause($ch, CURLPAUSE_CONT);
}
echo "块 {$downloadInfo['chunk_count']}: {$chunkSize} 字节, " .
"总计: {$downloadInfo['total_size']} 字节\n";
return $chunkSize;
},
CURLOPT_NOPROGRESS => false,
CURLOPT_PROGRESSFUNCTION => function($ch, $dlTotal, $dlNow, $ulTotal, $ulNow) {
if ($dlTotal > 0) {
$percent = round(($dlNow / $dlTotal) * 100, 2);
echo "进度: {$percent}% ({$dlNow}/{$dlTotal} 字节)\n";
}
return 0;
}
]);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo '错误: ' . curl_error($ch) . "\n";
} else {
$downloadTime = microtime(true) - $downloadInfo['start_time'];
$speed = $downloadInfo['total_size'] / $downloadTime;
echo "下载完成: {$downloadInfo['total_size']} 字节, " .
"耗时: " . round($downloadTime, 2) . " 秒, " .
"平均速度: " . round($speed, 2) . " 字节/秒\n";
}
curl_close($ch);
return $result;
}
// 控制回调函数 - 每接收3个数据块暂停一次
$controlCallback = function($info, $chunkSize) {
if ($info['chunk_count'] % 3 === 0) {
return 'pause_recv';
}
return 'continue';
};
// 使用示例
controlledDownload('https://httpbin.org/bytes/50000', $controlCallback);
function controlledUpload($url, $data, $chunkSize = 1024) {
$ch = curl_init();
// 准备上传数据
$dataLength = strlen($data);
$uploaded = 0;
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_READFUNCTION => function($ch, $fd, $length) use ($data, &$uploaded, $dataLength, $chunkSize) {
static $position = 0;
if ($position >= $dataLength) {
return ''; // 数据已发送完毕
}
// 读取指定大小的数据块
$chunk = substr($data, $position, min($chunkSize, $dataLength - $position));
$position += strlen($chunk);
$uploaded += strlen($chunk);
$percent = round(($position / $dataLength) * 100, 2);
echo "上传进度: {$percent}% ({$position}/{$dataLength} 字节)\n";
// 每上传1KB暂停100毫秒,模拟限速
if ($uploaded >= 1024) {
$uploaded = 0;
curl_pause($ch, CURLPAUSE_SEND);
usleep(100000); // 100毫秒
curl_pause($ch, CURLPAUSE_CONT);
}
return $chunk;
},
CURLOPT_INFILESIZE => $dataLength
]);
echo "开始上传 {$dataLength} 字节数据到 {$url}\n";
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo '上传错误: ' . curl_error($ch) . "\n";
} else {
echo "上传完成,服务器响应: " . strlen($response) . " 字节\n";
}
curl_close($ch);
return $response;
}
// 生成测试数据
$testData = str_repeat('0123456789', 1000); // 10KB数据
// 使用示例
controlledUpload(
'https://httpbin.org/post',
$testData,
512 // 每次上传512字节
);
暂停数据接收。当设置此标志时,cURL将暂停从服务器接收数据,直到调用 CURLPAUSE_CONT。
暂停数据发送。当设置此标志时,cURL将暂停向服务器发送数据,直到调用 CURLPAUSE_CONT。
暂停所有数据传输(接收和发送)。这是 CURLPAUSE_RECV | CURLPAUSE_SEND 的组合。
恢复暂停的数据传输。使用此标志可以恢复之前被暂停的接收或发送操作。
curl_pause() 函数需要PHP 5.5.0或更高版本,并且需要cURL 7.18.0或更高版本支持。
CURLOPT_WRITEFUNCTION 或 CURLOPT_READFUNCTION)中调用 curl_pause() 时,必须传递正确的cURL句柄参数。
A: curl_pause() 主要用于在cURL回调函数中调用,但也可以在传输过程中的其他地方调用。不过,在回调函数外部使用时需要谨慎,因为可能会影响正在进行的传输。
A: 暂停操作不会关闭连接,只是临时停止数据传输。连接保持打开状态,可以在恢复后继续传输数据。