2010-10-04 129 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库中有一个错误来防止这种情况发生。