2009-07-30 12 views
9

मुझे यहां एक साधारण समस्या है। मुझे एक साथ कई मेजबानों के साथ संवाद करने की ज़रूरत है, लेकिन मुझे वास्तव में किसी भी सिंक्रनाइज़ेशन की आवश्यकता नहीं है क्योंकि प्रत्येक अनुरोध काफी आत्मनिर्भर है।मैं गैर-अवरुद्ध सॉकेट कनेक्ट() के कैसे प्राप्त कर सकता हूं?

इसके कारण, मैंने धागे को स्पैम करने के बजाए एसिंक्रोनस सॉकेट के साथ काम करना चुना। अब मुझे एक छोटी सी समस्या है:

एसिंक सामान एक आकर्षण की तरह काम करता है, लेकिन जब मैं 100 होस्ट से कनेक्ट करता हूं, और मुझे 100 टाइमआउट (टाइमआउट = 10 सेकेंड) मिलते हैं तो मैं 1000 सेकंड प्रतीक्षा करता हूं, बस पता लगाने के लिए मेरे सभी कनेक्शन असफल रहे।

क्या गैर अवरोधक सॉकेट कनेक्ट करने का कोई तरीका है? मेरी सॉकेट पहले से ही गैर-लॉकिंग पर सेट है, लेकिन कनेक्ट करने के लिए कॉल() अभी भी अवरुद्ध हैं।

टाइमआउट को कम करना स्वीकार्य समाधान नहीं है।

मैं इसे पायथन में कर रहा हूं, लेकिन मुझे लगता है कि प्रोग्रामिंग भाषा वास्तव में इस मामले में कोई फर्क नहीं पड़ता।

क्या मुझे वास्तव में धागे का उपयोग करने की आवश्यकता है?

उत्तर

4

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

आप asyncore मॉड्यूल में प्रेषक वर्ग के साथ ऐसा कर सकते हैं। मूल http client example पर एक नज़र डालें। उस वर्ग के कई उदाहरण कनेक्ट पर एक-दूसरे को अवरुद्ध नहीं करेंगे। आप थ्रेड का आसानी से उपयोग कर सकते हैं, और मुझे लगता है कि सॉकेट टाइमआउट को ट्रैक करना आसान बनाता है, लेकिन चूंकि आप पहले ही एसिंक्रोनस विधियों का उपयोग कर रहे हैं, इसलिए आप उसी ट्रैक पर भी रह सकते हैं।

उदाहरण के लिए, अपने सभी Linux सिस्टम

import asyncore, socket 

class client(asyncore.dispatcher): 
    def __init__(self, host): 
     self.host = host 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.connect((host, 22)) 

    def handle_connect(self): 
     print 'Connected to', self.host 

    def handle_close(self): 
     self.close() 

    def handle_write(self): 
     self.send('') 

    def handle_read(self): 
     print ' ', self.recv(1024) 

clients = [] 
for i in range(50, 100): 
    clients.append(client('cluster%d' % i)) 

asyncore.loop() 

कहाँ cluster50 में पर निम्न काम करता है - cluster100, कई मशीनों है कि अनुत्तरदायी, या अस्तित्वहीन हैं देखते हैं। यह तुरंत प्रिंटिंग शुरू करता है:

Connected to cluster50 
    SSH-2.0-OpenSSH_4.3 

Connected to cluster51 
    SSH-2.0-OpenSSH_4.3 

Connected to cluster52 
    SSH-2.0-OpenSSH_4.3 

Connected to cluster60 
    SSH-2.0-OpenSSH_4.3 

Connected to cluster61 
    SSH-2.0-OpenSSH_4.3 

... 

हालांकि यह गेटड्रिन्फो को ध्यान में रखता है, जिसे अवरुद्ध करना है। यदि आपको डीएनएस प्रश्नों को हल करने में समस्याएं आ रही हैं, तो सब कुछ इंतजार करना होगा। आपको शायद अपने स्वयं के डीएनएस प्रश्नों को अलग से इकट्ठा करने की आवश्यकता है, और अपने एसिंक लूप

में आईपी पते का उपयोग करने की आवश्यकता है यदि आप एसिंककोर की तुलना में एक बड़ा टूलकिट चाहते हैं, तो Twisted Matrix पर एक नज़र डालें। इसमें प्रवेश करने के लिए थोड़ा भारी है, लेकिन यह पाइथन के लिए सबसे अच्छा नेटवर्क प्रोग्रामिंग टूलकिट है।

+0

के साथ ब्लॉक नहीं करता है ठीक है, मुझे यहां माफी माँगनी है। मैंने पाइथन डॉक्स से कोड लिया, इसलिए यह मेरा कोड नहीं था, मैंने इसे स्वीकार किया कि यह सही है। और यह काम नहीं किया। यह अक्सर मेरे साथ हुआ कि लोगों ने मुझे सलाह दी, जिसे उन्होंने खुद को भी सत्यापित नहीं किया। मैं कभी अनुमान लगा सकता था कि कोड के बजाए मेरा ओएस समस्या होगी, इसलिए मैंने सोचा कि आप केवल एक और लड़के हैं जो hes को समझते हैं और मुझे यह जांचने के बिना दस्तावेज कोड चिपकाते हैं। इसके लिए फिर से क्षमा करें। मैकोज़ समस्या थी, यह पता लगाने के लिए मैंने 6 घंटे बर्बाद कर, आज 3 पूर्ण संस्करणों को फेंक दिया। – Tom

+0

बीटीडब्ल्यू मैंने एक दोस्त के साथ अपने लिनक्स बॉक्स पर एक साथ फिर से परीक्षण किया, और यहां तक ​​कि getAddrInfo को ब्लॉक करने के लिए प्रतीत नहीं होता है। हमें एक त्रुटि मिलती है: [Errno 115] ऑपरेशन अब प्रगति पर है। तो सैद्धांतिक रूप से गैर प्रतिक्रियाशील मेजबान के साथ asyncore भी linux में काम कर सकता है। – Tom

+0

@ टॉम - एनपी, मैं मानता हूं कि यहां चारों ओर अनौपचारिक उत्तर हैं, खासकर गैर-खिड़कियों के खेतों में। इससे भी बदतर, क्या अनौपचारिक अंतहीन टीमों की टीम एक-दूसरे को वोट दे रही है, जिससे सही जवाब मिलना मुश्किल हो जाता है। – JimB

0

क्या आपने asyncore मॉड्यूल देखा था? बस आपको जो चाहिए वह हो सकता है।

+0

मैं इसका उपयोग कर रहा हूं, और यह अभी भी – Tom

8

select मॉड्यूल का उपयोग करें। यह आपको कई गैर-अवरुद्ध सॉकेट पर I/O पूर्ण होने की प्रतीक्षा करने की अनुमति देता है। चयन पर some more information है। से जुड़ा हुआ-टू पेज:

In C, coding select is fairly complex. In Python, it's a piece of cake, but it's close enough to the C version that if you understand select in Python, you'll have little trouble with it in C.

ready_to_read, ready_to_write, in_error = select.select(
        potential_readers, 
        potential_writers, 
        potential_errs, 
        timeout) 

You pass select three lists: the first contains all sockets that you might want to try reading; the second all the sockets you might want to try writing to, and the last (normally left empty) those that you want to check for errors. You should note that a socket can go into more than one list. The select call is blocking, but you can give it a timeout. This is generally a sensible thing to do - give it a nice long timeout (say a minute) unless you have good reason to do otherwise.

In return, you will get three lists. They have the sockets that are actually readable, writeable and in error. Each of these lists is a subset (possibly empty) of the corresponding list you passed in. And if you put a socket in more than one input list, it will only be (at most) in one output list.

If a socket is in the output readable list, you can be as-close-to-certain-as-we-ever-get-in-this-business that a recv on that socket will return something. Same idea for the writeable list. You'll be able to send something. Maybe not all you want to, but something is better than nothing. (Actually, any reasonably healthy socket will return as writeable - it just means outbound network buffer space is available.)

If you have a "server" socket, put it in the potential_readers list. If it comes out in the readable list, your accept will (almost certainly) work. If you have created a new socket to connect to someone else, put it in the potential_writers list. If it shows up in the writeable list, you have a decent chance that it has connected.

+0

कनेक्ट करने पर अवरुद्ध करता है, वह विशेष रूप से कहता है कि उसे कनेक्ट() पर अवरुद्ध किया जा रहा है। चयन केवल आपको बताता है कि क्या पठनीय या लिखने योग्य है। – JimB

+1

मेरे उत्तर का अंतिम पैरा देखें। 'चयन' मल्टीप्लेक्सिंग के साथ, आपको उपयोगी काम करने से पहले 1000 सेकंड प्रतीक्षा करने की आवश्यकता नहीं है। थोड़े समय के साथ, यदि आप सभी अंत बिंदुओं को कनेक्ट नहीं करते हैं, तो केवल थोड़ी देर प्रतीक्षा के साथ आप अभी भी उपयोगी काम कर सकते हैं। मुड़ना निश्चित रूप से एक विकल्प है, लेकिन जैसा कि आपने खुद कहा था "इसमें प्रवेश करने के लिए थोड़ा भारी है"। –

+0

आह, मुझे समस्या दिखाई देती है ... उसने एक टाइमआउट सेट किया, जिसका मतलब है कि सॉकेट * को अवरुद्ध करना है। – JimB

4

twisted का उपयोग करें।

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

+2

मुड़कर ऐसी खुशी लाती है। मैं हर दिन इसके साथ काम करता हूं और समेकन के साथ संघर्ष करने वालों को मनाने की कोशिश करता हूं कि यह उनके जीवन को इतना आसान बना देगा। बेशक, मेरे सहकर्मियों को कम से कम अंतर देखना पड़ता है। – Dustin

+1

मैंने पहले मोड़ का उपयोग किया है, यह काफी अच्छा है, लेकिन दस्तावेज़ीकरण भी मुड़ गया है। इसके अलावा मेरे स्रोत को एकीकृत करना मुश्किल होगा। क्या आप निश्चित हैं कि यह कनेक्ट पर अवरुद्ध नहीं होता है? उस समय के लिए जाने की कोशिश कर सकते हैं। – Tom

6

दुर्भाग्यवश कोई उदाहरण कोड नहीं है जो बग दिखाता है, इसलिए यह देखना मुश्किल है कि यह ब्लॉक कहां से आता है।

वह कुछ इस तरह है:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.setblocking(0) 
s.connect(("www.nonexistingname.org", 80)) 

सॉकेट मॉड्यूल आंतरिक getaddrinfo का उपयोग करता है, जो एक अवरुद्ध ऑपरेशन है, खासकर जब होस्ट नाम मौजूद नहीं है। मानक अनुपालन डीएनएस क्लाइंट कुछ समय इंतजार करेगा कि यह देखने के लिए कि वास्तव में नाम मौजूद नहीं है या यदि कुछ धीमी डीएनएस सर्वर शामिल हैं।

समाधान केवल आईपी पते से कनेक्ट करना है या एक डीएनएस क्लाइंट का उपयोग करना है जो pydns जैसे गैर-अवरुद्ध अनुरोधों की अनुमति देता है।

+0

जो समस्या के दिल में काफी कटौती करता है। मुझे लगता है कि मुझे DNS समस्याएं हैं। मेरे ऐप का व्यवहार (कम से कम प्रारंभिक चरण में) पोर्ट्सकेनर के समान ही है: मैं बहुत तेज परिणामों पर निर्भर हूं, चाहे कनेक्ट काम करता है या नहीं।Nonxistent होस्टनाम ब्लॉक पर getaddrinfo का उपयोग गैर अवरोधक सॉकेट के लिए भी ब्लॉक करता है, जो खराब है (मेरे लिए)। मैं कई गैर-मेजबान मेजबानों से भी जुड़ सकता हूं, और मैं प्रत्येक गैर-मेजबान मेजबान पर 10 सेकेंड का इंतजार नहीं कर सकता। – Tom

+1

मेरा उद्देश्य बहुत अलग था, लेकिन आदेश को बदलकर तय किया गया था। यानी पहले कनेक्टबैकिंग कनेक्ट करें। – Ben

+0

@ बेन ने मेरी समस्या भी तय की! धन्यवाद! – JeromeJ

संबंधित मुद्दे