2010-10-04 166 views
2

我寫了一些查詢adns的代碼。這個代碼的問題是它卡住了,怎麼樣?讓我來解釋一下:Python和ADNS,陷入無限循環

  • 說我dnslist是[ 「8.8.4.4」, 「8.8.8.8」, 「208.67.220.220」, 「208.67.222.222」, 「192.168.50.1」]
  • 它會從列表中彈出一個DNS並重新查詢它,現在這意味着將以相反的順序查詢DNS
  • 無論我做什麼,它都不會顯示它首先拾取的DNS的結果(在我們的示例中爲192.168.50.1 )
  • 我不知道,如果是DNS曾經這樣回答
    • 首先我改變DNS列表中只包含有最後的DNS服務器和鱈魚e執行得很好
    • 第二我用5個DNS服務器的舊列表,除了最後一個是由我管理的,所以我可以跟蹤代碼甚至查詢它與否,令我驚訝的是查詢確實發生。
    • 因此,我們得到結果,但是由於某種原因,結果永遠不會插入到resolved_hosts中,並且由於未插入結果,其長度將保持小於dnslist的長度,導致無限循環。

你認爲可能會造成這個問題,以及如何解決呢?

執行代碼結果

Inside class's init' 
Data 
host www.yahoo.com 
dnslist length 5 
intensity 1 
Inside resolve() 
inside finished_resolving() 
Resolved : 0/5 
Inside 'while not finished_resolving' 
Queue: 0/1 
Launching Querying for www.yahoo.com/1 on 192.168.50.1 
Queue: 1/1 
Launching Querying for www.yahoo.com/1 on 208.67.222.222 
inside collect_results() 
inside finished_resolving() 
Resolved : 0/5 
Inside 'while not finished_resolving' 
------------------------ CLIPPED ---------------- 
Inside 'while not finished_resolving' 
inside collect_results() 
Inside collect_results's for query in self.adns.completed() 
DNS used was208.67.222.222 
Answered : (0, 'any-fp.wa1.b.yahoo.com', 1286169807, ('69.147.125.65', '67.195.160.76')) 
Resolved www.yahoo.com to 69.147.125.65 using 208.67.222.222 
Resolved hosts count1 
And they are: 
{'208.67.222.222': '69.147.125.65'} 


inside finished_resolving() 
Resolved : 1/5 
Inside 'while not finished_resolving' 
Queue: 1/1 
Launching Querying for www.yahoo.com/1 on 208.67.220.220 
inside collect_results() 
inside finished_resolving() 
Resolved : 1/5 
Inside 'while not finished_resolving' 
-------------------------- CLIPPED -------------------- 
inside collect_results() 
Inside collect_results's for query in self.adns.completed() 
DNS used was208.67.220.220 
Answered : (0, 'any-fp.wa1.b.yahoo.com', 1286169790, ('67.195.160.76', '69.147.125.65')) 
Resolved www.yahoo.com to 67.195.160.76 using 208.67.220.220 
Resolved hosts count2 
And they are: 
{'208.67.222.222': '69.147.125.65', '208.67.220.220': '67.195.160.76'} 


inside finished_resolving() 
Resolved : 2/5 
Inside 'while not finished_resolving' 
Queue: 1/1 
Launching Querying for www.yahoo.com/1 on 8.8.8.8 
inside collect_results() 
inside finished_resolving() 
Resolved : 2/5 
Inside 'while not finished_resolving' 
-------------------------- CLIPPED -------------------- 
inside collect_results() 
Inside collect_results's for query in self.adns.completed() 
DNS used was8.8.8.8 
Answered : (0, 'eu-fp.wa1.b.yahoo.com', 1286169758, ('87.248.122.122',)) 
Resolved www.yahoo.com to 87.248.122.122 using 8.8.8.8 
Resolved hosts count3 
And they are: 
{'208.67.222.222': '69.147.125.65', '208.67.220.220': '67.195.160.76', '8.8.8.8': '87.248.122.122'} 


inside finished_resolving() 
Resolved : 3/5 
Inside 'while not finished_resolving' 
Queue: 1/1 
Launching Querying for www.yahoo.com/1 on 8.8.4.4 
inside collect_results() 
inside finished_resolving() 
Resolved : 3/5 
Inside 'while not finished_resolving' 
-------------------- CLIPPED ------------------------------------- 
inside collect_results() 
Inside collect_results's for query in self.adns.completed() 
DNS used was8.8.4.4 
Answered : (0, 'eu-fp.wa1.b.yahoo.com', 1286169757, ('87.248.122.122',)) 
Resolved www.yahoo.com to 87.248.122.122 using 8.8.4.4 
Resolved hosts count4 
And they are: 
{'208.67.222.222': '69.147.125.65', '208.67.220.220': '67.195.160.76', '8.8.8.8': '87.248.122.122', '8.8.4.4': '87.248.122.122'} 


inside finished_resolving() 
Resolved : 4/5 
Inside 'while not finished_resolving' 
inside collect_results() 
inside finished_resolving() 
Resolved : 4/5 
---------------- CLIPPED ------------------------------- 

(最後一個塊不斷重複,直到系統開始掛機,負載變爲高達24)

代碼

test.py

import adns 
from time import time 
from async_dns import AsyncResolver 



dnslist2 = ["8.8.4.4", "8.8.8.8", "208.67.220.220", "208.67.222.222", "192.168.50.1"] #192.168.50.1 is a dns server i manage 
host = "www.yahoo.com" 
record = adns.rr.A 
intensity = len(dnslist2)/5+1 

ar = AsyncResolver(dnslist2, host, record, intensity) 
start = time() 
resolved = ar.resolve() 
end = time() 

print "\n\n" 

for dns, ip in resolved.items(): 
    if ip is None: 
    print "%s could not resolv %s." % (dns, host) 
    else: 
    print "%s resolved it to %s : %s" % (dns, host, ip) 

print "\n\n----------------------------------------------------" 
print "It took %.2f seconds to query %d dns." % (end-start, len(dnslist)) 
print "----------------------------------------------------" 

async _dns.py

#!/usr/bin/python 
# 

import sys 
import adns 
from time import time 

class AsyncResolver(object): 
    def __init__(self, dnslist, host, record, intensity=10): 

     """ 
     dnslist: a list of dns used to resolve 
     host : hostname to resolve 
     record: recordtype to resolve 
     intensity: how many hosts to resolve at once 
     """ 
     print "Inside class's init'" 
     self.dnslist = dnslist 
     self.host = host 
     self.record = record 


     if intensity >= len(dnslist) : 
      self.intensity = len(dnslist)/5+1 
     else: 
      self.intensity = intensity 

     print "Data" 
     print "host " + host 
     print "dnslist length " + str(len(dnslist)) 
     print "intensity " + str(intensity) 




    def resolve(self): 
     """ Resolves hosts and returns a dictionary of { 'dns': 'ip' }. """ 
     print "Inside resolve()" 

     host = self.host 
     record = self.record 
     resolved_hosts = {} 
     active_queries = {} 
     dns_queue = self.dnslist[:] 

     def collect_results(): 
      print "inside collect_results()" 
      for query in self.adns.completed(): 
       print "Inside collect_results's for query in self.adns.completed()" 
       answer = query.check() 
       dns = active_queries[query] 
       print "DNS used was" + dns 
       print "Answered : " + str(answer) 
       del active_queries[query] 
       if answer[0] == 0: 
        #print "Inside answer[0] == 0 , ip:" + answer[3][0] 
        ip = answer[3][0] 
        resolved_hosts[dns] = ip 
        print "Resolved %s to %s using %s" % (host, ip, dns) 
        print "Resolved hosts count" + str(len(resolved_hosts)) 
        print "And they are: " 
        print str(resolved_hosts) 
        print "\n" 

       elif answer[0] == 101 and not record == adns.rr.CNAME: # CNAME if CNAME wasn't required' 
        print "ooopppps, i got a CNAME, gotta find its A" 
        print "\n" 
        query = self.adns.submit(answer[1], adns.rr.A) 
        active_queries[query] = dns 
       else: 
        resolved_hosts[dns] = None 
        print "THIS COULD NOT BE RESOLVED" 

     def finished_resolving(): 
      print "inside finished_resolving()" 
      print "Resolved : " + str(len(resolved_hosts)) + "/" + str(len(self.dnslist)) 
      return len(resolved_hosts) == len(self.dnslist) 

     while not finished_resolving(): 
      print "Inside 'while not finished_resolving'" 
      while dns_queue and len(active_queries) <= self.intensity: 
       print "Queue: " + str(len(active_queries)) + "/" + str(self.intensity) 
       dns = dns_queue.pop() 
       self.adns = adns.init(adns.iflags.noautosys,sys.stderr,"nameserver "+dns) 
       query = self.adns.submit(host, record) 
       print "Launching Querying for " + host + "/" + str(record) + " on " + dns 
       active_queries[query] = dns 
      collect_results() 
     return resolved_hosts 

回答

0

while not finished_resolving()循環將明顯繼續只要finished_resolving()返回true。該功能僅比較len(resolved_hosts)len(self.dnslist)。但是,據我所見,你永遠不會改變循環內部這些變量的長度,所以它會永遠持續下去。

在評論之後編輯這兩個塊中的任何一個都沒有影響兩個變量之一的長度。請解釋你如何看待他們正在改變。

+0

不準,錯誤的假設。請參閱collect_results()?而dns_queue和len(active_queries)<= self.intensity? – Shoaibi 2010-10-04 09:29:00

+0

resolved_hosts [dns] = ip裏面第一個如果在collect_results裏面,如果記錄已解析爲「A」記錄,則該值爲真。 – Shoaibi 2010-10-04 11:44:08

1

我剛剛嘗試使用adns python綁定,並遇到類似的問題 - 完成的查詢數組永遠不會完全填充,導致檢查循環運行到永遠。在我的情況下,似乎無法解決的域(由於NXDOMAIN等)從未被添加到完成的查詢數組(空值/空值)

我看了一下C綁定但看不到一個獨立的數據結構來保存失敗的結果,所以它確實看起來應該以某種方式將它們添加到「已完成」的查詢中。我懷疑在綁定或adns庫中有一個錯誤來防止這種情況發生。