【问题标题】:PHP cURL required only to send and not wait for responsePHP cURL 只需要发送而不等待响应
【发布时间】:2011-12-22 21:56:35
【问题描述】:

我需要一个 PHP cURL 配置,以便我的脚本能够发送请求并忽略 API 发送的答案。

curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
//curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100);
$result = curl_exec($ch);
echo $result;
curl_close ($ch);

我尝试添加: // curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); //curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100);

但它工作不正常,API 网络服务器没有收到请求。

原因是我正在向 API 发送大量请求,因此我的脚本非常慢,因为它等待每个请求。

感谢任何帮助。

【问题讨论】:

  • 这似乎比人们想象的要难。这是一篇关于这个问题和三种可能解决方案的好文章。 segment.com/blog/how-to-make-async-requests-in-php TLDR:您可以使用 pfsockopen 打开持久套接字连接或分叉 curl 进程,或者如果您不关心实际请求的延迟(例如在日志场景中),您可以将您的请求记录到日志文件并让 cron 等后台进程使用日志条目带外发送请求。

标签: php curl


【解决方案1】:

如何判断请求是否成功?您至少需要等待来自服务器的状态码才能确定。如果延迟是问题,请查看 curl multi API 以并行执行多个请求。一旦返回状态码,您应该能够设置写回调函数以中止接收返回的数据。

【讨论】:

  • 非常老的答案,但这种模式的重点是你不在乎。想想低优先级的跟踪调用,您希望能够在不关心响应的情况下发送请求,以最大限度地减少大量微小的低重要性请求的服务器负载。
【解决方案2】:

如果可能,您可以在后台运行wget(使用exec)

【讨论】:

  • 这并不能解决问题。相当于后台curl,还是会有进程等待响应,消耗计算资源。
  • 不是最好的主意
【解决方案3】:

发件人文件示例./ajax/sender.php

下面我们尝试在不等待应答的情况下对 php 脚本进行 ping 操作

    $url = 'https://127.0.0.1/ajax/received.php';
    $curl = curl_init();                
    $post['test'] = 'examples daata'; // our data todo in received
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt ($curl, CURLOPT_POST, TRUE);
    curl_setopt ($curl, CURLOPT_POSTFIELDS, $post); 
    
    curl_setopt($curl, CURLOPT_USERAGENT, 'api');

    //curl_setopt($curl, CURLOPT_TIMEOUT, 1); //if your connect is longer than 1s it lose data in POST better is finish script in recevie
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl,  CURLOPT_RETURNTRANSFER, false);
    curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 1);
    curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 10); 
    
    curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
    
    curl_exec($curl);   
    
    curl_close($curl);  

接收文件示例./ajax/received.php

如果您使用 fastcgi,请编辑 2019 年,只需完成 fastcgi 和浏览器关闭连接,但脚本仍将运行到最后。

如何完成脚本: PHP mod_fcgi with fastcgi_finish_request();

对于 Apache2:

ob_end_flush();
flush();

对于 php-fpm

fastcgi_finish_request(); $this->db->query('UPDATE new_hook_memory SET new=new+1 WHERE id=1');

旧版本:

ob_end_clean(); //if our framework have turn on ob_start() we don't need bufering respond up to this script will be finish 
    header("Connection: close\r\n"); //send information to curl is close
    header("Content-Encoding: none\r\n"); //extra information 
    header("Content-Length: 1"); //extra information
    ignore_user_abort(true); //script will be exisits up to finish below query even web browser will be close before sender get respond

    //we doing here what we would like do
    $this->db->query('UPDATE new_hook_memory SET new=new+1 WHERE id=1');    

 

【讨论】:

  • 不要在代码中添加任何注释吗?这是没用的。
  • 这可行,但如果你设置的超时时间太小(在我的情况下为 10 毫秒),它会在请求完全发送之前被中断。
  • 一些解释:此代码产生一个 cURL 错误代码 28:« Operation timed out after 1000 milliseconds with 0 out of -1 bytes received »。 ($data 是假的)。这个 sn-p 使用的技巧在于简单地忽略这个错误,因为它不会传播到 PHP。 cURL 发送的查询继续其生命。但是你不知道查询是否被主机接受了。
  • @skrol29 此示例适用于包含 ip 或主机的单向流,您需要信任主机或 ip。是不等待响应的简单解决方案。如果你想使用重要的数据并且有保证,你应该使用像 rabitmq 这样的不同方法来进行更多的控制。即使你不需要知道什么 curl 结果。就像 ping 到 php 一样,进行 count+1 之类的包含操作
  • 现在不能用php7发送异步请求还是使用线程?
【解决方案4】:

现在有点晚了,但对于任何感兴趣的人来说,解决方案是 CURLOPT_RETURNTRANSFER 需要设置为 TRUE,而不是 false。这样curl_exec 函数会立即返回一个值,而不是等待请求完成后再返回 - 即它以异步方式而不是同步方式运行。

例子:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

【讨论】:

  • Reza 问了些别的问题
  • 将 CURLOPT_RETURNTRANSFER 设置为 true 可确保我立即获得返回值,而不必等待请求完成。这不是 OP 要求的吗?
  • 如果您调用的服务器延迟 30 秒才能为您提供价值和响应,您如何立即获得价值?
  • Curl_setopt 总是立即返回,因为需要在启动连接之前设置选项。这个答案没有任何意义,是错误的,并且没有回答 OP 的问题
  • curl_exec(不是 curl_setopt)将立即返回或等待外部服务器响应,具体取决于使用 curl_setopt 设置的 CURLOPT_RETURNTRANSFER 的值。感谢您指出这一点 - 我已经编辑了我的答案。
【解决方案5】:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);
curl_exec($ch);
curl_close($ch);

这对我很有效。
在 PHP 7.1.14 Windows 上测试

【讨论】:

  • 这个打印响应,如何禁用它?
  • @Hassaan: curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE)
  • @MarcoDemaio 据我所知,这将使脚本等待响应
  • @l00k,我认为 Hassaan 在他的评论中询问了如何不打印出对curl_exec($ch);的调用结果
【解决方案6】:

这两种解决方案对我很有效

(当然已经很久了,但我不认为这个问题已经过时了)

使用 file_get_contents:

  //url of php to be called

$url = "example.php/test?id=1";

  //this will set the minimum time to wait before proceed to the next line to 1 second

$ctx = stream_context_create(['http'=> ['timeout' => 1]]);

file_get_contents($url,null,$ctx);

  //the php will read this after 1 second 

使用 cURL:

  //url of php to be called

$url = "example.php/test?id=1";

$test = curl_init();

  //this will set the minimum time to wait before proceed to the next line to 100 milliseconds

curl_setopt_array($test,[CURLOPT_URL=>$url,CURLOPT_TIMEOUT_MS=>100,CURLOPT_RETURNTRANSFER=>TRUE]);

curl_exec($test);

  //this line will be executed after 100 milliseconds

curl_close ($test); 

在这两种情况下,被调用的php都必须设置ignore_user_abort(true)。

两种情况下都不会打印结果,但是要注意你设置的超时时间,它需要大于被调用的php需要开始产生结果的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-18
    • 2012-12-30
    • 2011-01-12
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多