在使用php進行dns查詢的服務中,經常會出現超時的情況。這種問題一般是由于網絡連接不穩定或者dns服務器響應時間過長所導致。而這些問題都會導致當前程序無法得到正確的dns解析結果,從而導致整個服務的不穩定。所以在使用php進行dns查詢時,必須加以重視和處理。
我們來看一個簡單的例子。假設我們有一個域名解析的函數,代碼如下所示:
function getHostIp($domainName) { $ip = gethostbyname($domainName); return $ip; }在調用該函數時,我們傳入一個域名,然后就能得到這個域名對應的ip地址。但是,如果因為網絡問題或dns服務器響應太慢,這次查詢耗時過長,那我們應該怎么處理呢? 一種常見的手段就是設置超時時間。我們可以使用php的set_time_limit函數在查詢開始之前先設置一個超時時間,如果這個時間內沒有得到結果,我們就停止當前查詢。代碼如下所示:
function getHostIp($domainName) { $startTime = time(); $ip = gethostbyname($domainName); $endTime = time(); if (($endTime - $startTime) >1) { die("dns query timeout!"); } return $ip; }在上述代碼中,我們先調用time函數,獲取函數開始執行的時間,然后進行dns解析。最后再一次調用time函數獲取當前執行時間并與剛剛開始執行時間相減,如果結果大于1秒,就認為dns查詢超時,并返回錯誤信息停止當前程序的執行。 當然,上述方式處理超時不夠科學,還可以使用socket連接來對dns進行查詢,設置超時時間,并進行重試,以此來解決dns超時的問題。代碼如下所示:
function getHostIp($domainName) { $dnsResolver = array( '8.8.8.8', //google的dns地址 '114.114.114.114' //國內著名的dns地址 ); $timeout = 1; //超時時間為1s $maxRetry = 2; //最多重試2次 $ip = ''; foreach ($dnsResolver as $key =>$dns) { for ($i = 1; $i<= $maxRetry; $i++) { $sock = fsockopen($dns, 53, $errno, $errstr, $timeout); if (!$sock) { continue; } stream_set_timeout($sock, $timeout); fwrite($sock, "\n"); $response = fread($sock, 1024); fclose($sock); if ($response) { $ip = gethostbyname($domainName); if (!empty($ip)) { return $ip; } } } } return $ip; }在上述代碼中,我們先定義了兩個dns服務器地址,然后設置查詢超時時間為1秒,最多可重試兩次。然后使用fsockopen函數打開一個socket連接,進行查詢。如果查詢時成功得到了dns響應,則調用php的gethostbyname函數得到對應的ip地址。在查詢失敗或得到結果超時時,我們就進行重試。如果兩次重試后還是查詢不到結果,我們就返回空字符串。 總結來說,在進行php的dns查詢服務時,會經常遇到超時的問題。為了解決這類問題,我們可以使用以下方式: 1、設置查詢超時時間,當超過指定時間后,就認為查詢失敗并停止當前服務的執行; 2、使用socket連接進行查詢,并設置查詢超時時間和重試次數,以此解決超時問題。
上一篇php dns 劫持