2009-07-31 11 views
8

मैंने अभी पाइथन और धागे के साथ थोड़ा सा खेला, और एक बहुप्रचारित लिपि में भी एहसास हुआ, DNS अनुरोध अवरुद्ध हो रहे हैं। आयात थ्रेड आयात सॉकेटपाइथन इंटरप्रेटर बहुभाषी DNS अनुरोध ब्लॉक करता है?

class Connection(Thread): 
    def __init__(self, name, url): 
     Thread.__init__(self) 
     self._url = url 
     self._name = name 

    def run(self): 
     print "Connecting...", self._name 
     try: 
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
      s.setblocking(0) 
      s.connect((self._url, 80)) 
     except socket.gaierror: 
      pass #not interested in it 
     print "finished", self._name 


if __name__ == '__main__': 
    conns = [] 
    # all invalid addresses to see how they fail/check times 
    conns.append(Connection("conn1", "www.2eg11erdhrtj.com")) 
    conns.append(Connection("conn2", "www.e2ger2dh2rtj.com")) 
    conns.append(Connection("conn3", "www.eg2de3rh1rtj.com")) 
    conns.append(Connection("conn4", "www.ege2rh4rd1tj.com")) 
    conns.append(Connection("conn5", "www.ege52drhrtj1.com")) 

    for conn in conns: 
     conn.start() 

मैं जानता हूँ कि वास्तव में कितनी देर टाइमआउट है न सूत्रण से

, लेकिन जब यह चल रहा है निम्न होता है:: निम्न स्क्रिप्ट पर विचार करें

  1. सभी धागे शुरू और मुझे अपने प्रिंटआउट
  2. प्रत्येक एक्सएक्स सेकेंड, एक थ्रेड डिस्प्ले एक बार
  3. टी पर सभी के बजाय समाप्त हो गया वह थ्रेड्स अनुक्रमिक रूप से खत्म होता है, सभी एक बार नहीं (टाइमआउट = सभी के लिए समान!)

तो मेरा एकमात्र अनुमान यह है कि इसे जीआईएल के साथ करना है? स्पष्ट रूप से धागे एक साथ अपने कार्य नहीं करते हैं, एक समय में केवल एक कनेक्शन का प्रयास किया जाता है।

क्या कोई इस के आसपास एक रास्ता जानता है?

(asyncore does not मदद, और मैं अब के लिए मुड़ उपयोग करने के लिए नहीं करना चाहते हैं) नहीं यह इस सरल छोटी बात अजगर के साथ करवाने के लिए संभव है?

अभिवादन, टॉम

संपादित करें:

मैं MacOSX पर हूँ, मैं सिर्फ मेरे दोस्त लिनक्स पर इस चलाते हैं, और वह वास्तव में परिणाम मैं प्राप्त करने के लिए कामना की प्राप्त करता है। उसकी सॉकेट.कनेक्ट्स() की वापसी तुरंत, एक गैर थ्रेडेड वातावरण में भी। और यहां तक ​​कि जब वह अवरुद्ध करने के लिए सॉकेट सेट करता है, और 10 सेकंड तक टाइमआउट करता है, तो उसके सभी थ्रेड एक ही समय में समाप्त होते हैं।

क्या कोई इसे समझा सकता है?

+1

तुम सिर्फ socket.getaddrinfo का उपयोग कर का प्रयास किया है (मेजबान, बंदरगाह) यह देखने के लिए कि क्या एक ही सीमा है? दुर्भाग्य से मैं इसे दोहराना नहीं कर सकता, क्योंकि यह एक डीएनएस समस्या है। ज्यादातर मामलों में, आपको "gaierror: (-2, 'नाम या सेवा ज्ञात नहीं है')" जल्दी से प्राप्त करना चाहिए। – JimB

+0

हाँ मैंने कोशिश की है, और इसकी एक ही सीमा है। – Tom

+0

मुझे पूरा यकीन है कि ओएसएक्स बीएसडी पुस्तकालयों से getaddrinfo का उपयोग करता है, जो शायद नीचे <मार्टिन बनाम लोविस> द्वारा सूचीबद्ध प्रतिबंध है। – JimB

उत्तर

15

कुछ सिस्टमों पर, getaddrinfo थ्रेड-सुरक्षित नहीं है। पायथन का मानना ​​है कि ऐसे कुछ सिस्टम फ्रीबीएसडी, ओपनबीएसडी, नेटबीएसडी, ओएसएक्स, और वीएमएस हैं। उन प्रणालियों पर, पायथन विशेष रूप से netdb (यानी getaddrinfo और दोस्तों) के लिए एक ताला रखता है।

तो यदि आप ऑपरेटिंग सिस्टम स्विच नहीं कर सकते हैं, तो आपको ट्विस्ट की तरह एक अलग (थ्रेड-सुरक्षित) रिज़ॉल्वर लाइब्रेरी का उपयोग करना होगा।

+2

+1 मुड़ता हुआ उपयोग करें! – nosklo

+0

मुझे इसे बहुत तेज़ी से करने की ज़रूरत है, लेकिन मैंने अभी मुड़ने पर एक पुस्तक का आदेश दिया है, लोगों को वास्तव में यह पसंद है, ऐसा नहीं हो सकता सब के बाद बुरा। इसमें थोड़ा सा प्रयास करने की कोशिश की जाएगी, लेकिन मैं हाल ही में व्यस्त हूं। – Tom

+0

अन्य पायथन रिज़ॉल्वर लाइब्रेरीज़ हैं, जैसे कि डेंस्पीथन और पायडन्स, जो मुड़ने से उपयोग करने में आसान हो सकते हैं। y पूरी तरह से थ्रेड-सुरक्षित नहीं है (प्रत्येक DNS अनुरोध के लिए एक नया यूडीपी सॉकेट बनाना, और इस प्रकार संभावित रूप से थकाऊ बंदरगाह संख्या), लेकिन यदि आप कई प्रश्न नहीं करते हैं तो यह कोई समस्या नहीं हो सकती है। –

2

अगर यह उपयुक्त है आप इस प्रक्रिया के आधार पर समानांतरवाद

import multiprocessing, socket 

NUM_PROCESSES = 5 

def get_url(url): 
    try: 
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     s.setblocking(0) 
     s.connect((url, 80)) 
    except socket.gaierror: 
     pass #not interested in it 
    return 'finished ' + url 


def main(url_list): 
    pool = multiprocessing.Pool(NUM_PROCESSES) 
    for output in pool.imap_unordered(get_url, url_list): 
     print output 

if __name__=="__main__": 
    main(""" 
      www.2eg11erdhrtj.com 
      www.e2ger2dh2rtj.com 
      www.eg2de3rh1rtj.com 
      www.ege2rh4rd1tj.com 
      www.ege52drhrtj1.com 
      """.split()) 
+0

क्या कोई उत्तर या प्रश्न है? : पी – Tom

+0

अच्छा, इसमें कोड है ... तो एक जवाब! –

+0

यह 2.5 में उपलब्ध नहीं है। यह पूरी तरह से काम करता है। – jack

1

संदेश DNS अनुरोधों एसिंक्रोनस रूप Twisted Names का उपयोग कर सक्षम करने के लिए multiprocessing मॉड्यूल इस्तेमाल कर सकते हैं:

import sys 
from twisted.internet import reactor 
from twisted.internet import defer 
from twisted.names import client 
from twisted.python import log 

def process_names(names): 
    log.startLogging(sys.stderr, setStdout=False) 

    def print_results(results): 
     for name, (success, result) in zip(names, results): 
      if success: 
       print "%s -> %s" % (name, result) 
      else: 
       print >>sys.stderr, "error: %s failed. Reason: %s" % (
        name, result) 

    d = defer.DeferredList(map(client.getHostByName, names), consumeErrors=True) 
    d.addCallback(print_results) 
    d.addErrback(defer.logError) 
    d.addBoth(lambda _: reactor.stop()) 

reactor.callWhenRunning(process_names, """ 
    google.com 
    www.2eg11erdhrtj.com 
    www.e2ger2dh2rtj.com 
    www.eg2de3rh1rtj.com 
    www.ege2rh4rd1tj.com 
    www.ege52drhrtj1.com 
    """.split()) 
reactor.run() 
संबंधित मुद्दे