日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

【PHP】curl_init() 如何排错????

發(fā)布時間:2025/3/20 php 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【PHP】curl_init() 如何排错???? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 場景
    • 期望
    • 問題
    • 解決思路
      • 考慮超時重試情況;
      • 考慮DNS緩存;
      • 輸出curl_error($ch);
    • 最終結果
    • 擴展鏈接
    • 其他錯誤解決方法:
      • SSL: no alternative certificate subject name matches target host name
      • curl: (60) SSL certificate problem: unable to get local issuer certificate
      • Empty reply from server

場景

function httpGetWebInfo($url, $iptype = 6, $resolve = [], $timeout = 120) {// $header = ["Cache-Control: no-cache"];$data = [];$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); //post方式提交curl_setopt($ch, CURLOPT_NOSIGNAL, true); // 為true,會導致DNS解析不受時間控制curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);curl_setopt($ch, CURLOPT_HEADER, false); // 不需要輸出頭部信息 -Icurl_setopt($ch, CURLOPT_NOBODY, true); // 不輸出內容curl_setopt($ch, CURLOPT_IPRESOLVE, 4 == $iptype ? CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_V6);curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); //設置是否將響應結果存入變量,1是存入,0是直接echo出;curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //抓取跳轉 -L --location// curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // HTTP 頭字段的數組// curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); // 強制獲取一個新的連接,而不是緩存中的連接// curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 0); // 禁用DNS緩存 if (!empty($resolve)) {// curl -L -I -6 www.a.com --resolve www.a.com:80:<ipaddr>curl_setopt($ch, CURLOPT_RESOLVE, $resolve);curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); //禁用DNS全局緩存}curl_exec($ch);if (!curl_errno($ch)) {$data = curl_getinfo($ch);}curl_close($ch);return $data; }# 調用 $domainIPAddr = ['www.b.com' => '1.1.1.1','www.b.com' => '240c::2', ];foreach ($domainIPAddr as $domain => $ipaddr) {var_dump(getDnsRecord($domain, DNS_AAAA));$iptype = 判斷ipaddr 類型 ? 4 : 6;$curl = httpGetWebInfo($domain, $iptype, ["{$domain}:80:{$ipaddr}"]);var_dump($curl);$state = empty($curl ) ? 0 : $curl ['http_code'];var_dump([$domain=>$state]); }## 問題: 當打印出resolve IPv6時的 curl 缺總是顯示 IPv4的信息解決方式: 添加curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);

期望

使用IPv6解析DNS,并返回狀態(tài)碼

問題

通過CURLOPT_IPRESOLVE 控制使用IPv4解析域名還是IPv6解析,

但是當解析的域名不存在IPv6時,仍舊返回200的狀態(tài)碼,

curl_setopt($ch, CURLOPT_NOSIGNAL, true); curl_setopt($ch, CURLOPT_IPRESOLVE, 4 == $iptype ? CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_V6);

解決思路

考慮超時重試情況;

因為 curl在請求時,會默認請求域名解析的ipv6地址,如果ipv6地址請求失敗,會timeout秒后請求正常的ipv4地址,所以這個時候,我們強制設置curl請求時,用ipv4地址

后經過排查返回的是結果是使用IPv4地址解析的,所以一直報200;
是因為 curl_setopt($ch, CURLOPT_NOSIGNAL, true); 導致DNS解析不受超時限制,會自動解析IPv4;
開啟 CURLOPT_NOSIGNAL 導致DNS解析不受超時限制

考慮DNS緩存;

所以找如何清理DNS緩存;

無法從PHP手動清除DNS緩存。但是你可以使用 CURLOPT_DNS_CACHE_TIMEOUT,您可以將選項設置為0,以用于下一個請求以強制刷新curl的DNS緩存

Pass a long, this sets the timeout in seconds. Name resolves will be kept in memory and used for this number of seconds. Set to zero to completely disable caching, or set to -1 to make the cached entries remain forever. By default, libcurl caches this info for 60 seconds.

curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 0); // 禁用DNS緩存 無效 curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); //禁用DNS全局緩存 有效另補充:禁用鏈接緩存 curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // HTTP 頭字段的數組 curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); // 強制獲取一個新的連接,而不是緩存中的連接

輸出curl_error($ch);

報錯信息:curl(7) xxxx permission denied
然后tcpdump 抓包,發(fā)現從 私網IPv6 出發(fā)的只有發(fā)包沒有回包,也就是說進不到私網地址
所以考慮 在ip6tables上創(chuàng)建轉發(fā)規(guī)則 ip6tables -I FORWARD -d <私網IPv6> -j ACCEPT

最終結果

ip6tables -I FORWARD -d <私網IPv6> -j ACCEPT

function httpGetWebInfo($url, $iptype = 6, $resolve = [], $timeout = 10) {$data = [];$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); //post方式提交curl_setopt($ch, CURLOPT_NOSIGNAL, FALSE); // 如何為true,會導致DNS解析不受時間控制,導致程序一直pendingcurl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);curl_setopt($ch, CURLOPT_HEADER, true); // 不需要輸出頭部信息 -Icurl_setopt($ch, CURLOPT_NOBODY, true); // 不輸出內容curl_setopt($ch, CURLOPT_IPRESOLVE, 4 == $iptype ? CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_V6);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //設置是否將響應結果存入變量,1是存入,0是直接echo出;curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //抓取跳轉 -L --locationif (!empty($resolve)) {// curl -L -I -6 www.a.com --resolve www.a.com:80:<ipaddr>curl_setopt($ch, CURLOPT_RESOLVE, $resolve);curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); //禁用DNS全局緩存 關鍵}curl_exec($ch);if (!curl_errno($ch)) {$data = curl_getinfo($ch);}curl_close($ch);return $data; }

擴展鏈接

【PHP】 獲取網站信息

如果要支持毫秒級別的超時設置必須加CURLOPT_NOSIGNAL, 否則直接返回超時,
當設置了小于1000ms的超時以后, curl不會發(fā)起任何請求,而直接返回超時錯誤(Timeout reached 28)】,這是PHP的坑,參考: http://www.laruence.com/2014/01/21/2939.html
timeout支持毫秒數在cURL 7.16.2中被加入,從PHP 5.2.3起可使用。

其他錯誤解決方法:

SSL: no alternative certificate subject name matches target host name

curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

參考:https://www.php.net/manual/zh/function.curl-setopt.php#75711

curl: (60) SSL certificate problem: unable to get local issuer certificate

curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); // false 禁止 cURL 驗證對等證書(peer's certificate)

參考:https://stackoverflow.com/questions/24611640/curl-60-ssl-certificate-problem-unable-to-get-local-issuer-certificate

Empty reply from server

1、檢查你的代理服務器是否正常。可能當前代理服務器無法正常訪問
2、增加超時時間,每次請求接口時間略長一些就會產生這個錯誤

總結

以上是生活随笔為你收集整理的【PHP】curl_init() 如何排错????的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。