2011-09-07 17 views
9

पर भेजने के लिए स्थानीय आईपी पता प्राप्त करें। मैं एक सर्वर पर यूडीपी पैकेट भेजने के लिए एक पायथन स्क्रिप्ट का उपयोग कर रहा हूं जो सर्वर से अधिसूचनाएं प्राप्त करने के लिए मेरी स्क्रिप्ट पंजीकृत करेगा। प्रोटोकॉल की आवश्यकता है कि मैं अपना स्वयं का आईपी पता और पोर्ट भेजूं जिस पर मैं इन सूचनाओं को प्राप्त करना चाहता हूं, इसलिए यह एक ऐसा पता होना चाहिए जो सर्वर के नेटवर्क से पहुंच योग्य हो।पायथन: आईपी डेटा को एक विशिष्ट रिमोट आईपी-एड्रेस

समाधान कम से कम विंडोज एक्सपी और ऊपर और अधिमानतः मैक ओएस एक्स पर काम करना चाहिए, क्योंकि यह मेरा विकास मंच है।

पहला कदम मेरे किसी भी इंटरफेस का आईपी पता प्राप्त करना है। मैं वर्तमान में मशीनों के अपने होस्ट नाम को हल करने के सामान्य रूप से सुझाए गए दृष्टिकोण का उपयोग कर रहा हूं:

def get_local_address(): 
    return socket.gethostbyname(socket.gethostname()) 

यह कभी-कभी काम करता है। वर्तमान में यह 172.16.249.1 लौटाता है, जो वीएम वेयर द्वारा उपयोग किए जाने वाले वर्चुअल इंटरफ़ेस का पता है, इसलिए यह एक समस्या है।

डिफ़ॉल्ट इंटरफ़ेस का आईपी पता प्राप्त करने का एक बेहतर तरीका होगा, जो कि सही समय पर सही होना चाहिए।

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

def get_address_to_connect_to(server_addr): 
    non_open_port = 50000 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

    try: 
     s.connect((server_addr, non_open_port)) 
    except socket.error: 
     pass 
    else: 
     s.close() # just in case 

    return s.getsockname()[0] 

यह जब तक कुछ TCP समयबाह्य मामले कि सर्वर तक नहीं पहुंचा जा या बीच में एक बुराई फ़ायरवॉल ICMP ब्लॉक कर रहा है पूरी हो गई है को अवरुद्ध कर देगा पैकेट। क्या उस जानकारी को पाने का कोई बेहतर तरीका है?

उत्तर

11

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

एकमात्र समाधान जो मुझे मिल सकता है वह प्लेटफॉर्म पर भरोसेमंद काम करता है, जैसा कि आप कर रहे हैं, कनेक्शन का प्रयास करना है। आपके कोड पर एक सुधार टीसीपी के बजाय यूडीपी का उपयोग करना है, यानी SOCK_STREAM के बजाय SOCK_DGRAM। यह कनेक्ट टाइमआउट से बचाता है, और फ़ंक्शन बस पूर्ण हो जाता है।

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

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

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 

try: 
    s.connect((host, 9)) 
    client = s.getsockname()[0] 
except socket.error: 
    client = "Unknown IP" 
finally: 
    del s 
return client 

मुझे लगता है कि आप 0.0.0.0 हो रही है क्योंकि आप getsockname कॉल करने से पहले सॉकेट बंद करने जा रहे हैं: यहां मोटे तौर पर कोड मैं प्रयोग किया जाता है। एक और टिप पोर्ट 9 का उपयोग है; यह आरएफसी 863 यूडीपी डिस्कार्ड बंदरगाह है, और इसलिए कुछ यादृच्छिक उच्च-क्रमांकित बंदरगाह की तुलना में थोड़ा कम अजीब है।

+0

आह, मीठा सहानुभूति! 'SOCK_DGRAM' के साथ, यह निकट-सही होगा! लेकिन मेरे मामले में 's.getsockname()' रिटर्न '('0.0.0.0', 51770)'। मैंने 's = socket.socket (socket.AF_INET, सॉकेट.SOCK_DGRAM) की कोशिश की है; s.sendto (b'hello ', (' 1.2.3.4 ', 50000)); s.getsockname() [0] '। यदि आप अपना कोड अपने उत्तर में जोड़ते हैं तो यह बहुत अच्छा होगा! – Feuermurmel

+0

मेरे संपादन को उत्तर में देखें। – DNS

+0

यह पूरी तरह से काम करता है; यह [डिस्कार्ड प्रोटोकॉल] का भी उपयोग करता है (http://en.wikipedia.org/wiki/Discard_Protocol) मुझे नहीं पता था! मैंने 'डेल एस' को 'साथ' कथन के साथ बदल दिया। – Feuermurmel

0

क्या भेजने वाले पक्ष को अपना आईपी पता जानने की आवश्यकता है?

क्लाइंट सिर्फ यूडीपी 'रजिस्टर' भेजने के बाद (सभी इंटरफेस पर) की सदस्यता लेने की कोशिश कर रहे डेटा के लिए नहीं सुन सकता है और क्या सर्वर बस उस डेटा को डेटा भेजना शुरू कर देता है जिससे डेटाग्राम उत्पन्न हुआ?

+0

हेरेसी! यह सेवा मेरे जीवन को आसान बनाने के लिए बहुत सी चीजें कर सकती है। लेकिन एसआईपी कार्यान्वयन में भी यही समस्या दिखाई देती है जो परियोजना का भी हिस्सा है।इसे 'रजिस्ट्रार' अनुरोध के 'संपर्क' शीर्षलेख में अपना स्वयं का आईपी पता भेजना होगा। – Feuermurmel

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