2012-04-01 22 views
7

मैं अजगर में एक कच्चे सॉकेट कि केवल यूडीपी पैकेट के लिए सुनता है बनाने के लिए कोशिश कर रहा हूँ:पाइपन कच्चे सॉकेट यूडीपी पैकेट के लिए सुन रहा है; पैकेट का केवल आधा प्राप्त

import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP) 
s.bind(('0.0.0.0', 1337)) 
while True: 
    print s.recvfrom(65535) 

इस रूट के रूप में चलाने के लिए जरूरत है, और बंदरगाह 1337 पर एक रॉ सॉकेट बनाता है , जो यूडीपी पैकेट के लिए सुनता है और जब भी उन्हें प्राप्त होता है उन्हें प्रिंट करता है; वहां कोई समस्या नहीं है।

import socket 
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
c.connect(('127.0.0.1', 1337)) 
c.send('message 1') 
c.send('message 2') 
c.send('message 3') 
c.send('message 4') 
c.send('message 5') 
c.send('message 6') 

लगातार, केवल, पहले तीसरे और पांचवें संदेश (message 1, message 3 और message 5) के माध्यम से मिल जाएगा और सर्वर में मुद्रित किया:

अब अगर यह काम करता है परीक्षण करने के लिए एक छोटे से ग्राहक बनाते हैं उत्पादन। , दूसरे चौथे और छठे संदेश सर्वर उत्पादन पर दिखाई नहीं देती हैं, और बदले में ग्राहक एक अपवाद हो जाता है:

>>> c.send('message 2') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
socket.error: [Errno 111] Connection refused 

Wireshark में यह चल रहा है पता चलता है कि यह "गंतव्य तक नहीं पहुंचा जा" के लिए एक ICMP जबाब हो रही है। मैं इसे 3 अलग मशीनों पर पुन: उत्पन्न करने में सक्षम हूं (हालांकि सभी चल रहे लिनक्स)। क्या मैं कुछ भूल रहा हूँ? क्या यूडीपी के लगातार पैकेट ड्रॉप करने के लिए यह अपेक्षित व्यवहार है, क्योंकि इसका उपयोग करने वाले प्रोटोकॉल को पैकेट नुकसान का सहिष्णु माना जाता है? फिर भी, स्थानीय इंटरफेस पर भेजे जाने पर पैकेट क्यों गिराए जाएंगे?

के बजाय सर्वर को 127.0.0.1 पर बाध्यकारी एक ही परिणाम है।

+0

संदेश स्टैक के साथ कभी-कभी अजीब चीजें होती हैं। इस मामले में ईथरनेट एडेप्टर लूपबैक का उपयोग करता है, लेकिन फिर भी, पैकेट "phsically" अभी भी कार्ड पर जाते हैं और फिर संदेश कतार को ऑर्डर करने के लिए ड्राइवर द्वारा व्याख्या की जाती है। मदद करने के लिए बस कुछ शोध बिंदु। – FlavorScape

+0

@Etienne, FlavorScape मुझे हर दूसरे पैकेट में त्रुटि मिलती है, जो नेटवर्क त्रुटि होने के लिए बहुत नियमित लगता है ... – brice

+0

हां, यह हर दो पैकेट होता है, जिसका अर्थ है कि यदि आप '2 * एन' पैकेट भेजते हैं, तो सभी पैकेट फॉर्म '2 * i + 1' के माध्यम से नहीं मिलेगा। मुझे नहीं लगता कि यह पैकेट नुकसान हो सकता है, क्योंकि यह सब स्थानीय इंटरफ़ेस पर है। –

उत्तर

7

इसे मूर्खतापूर्ण ढंग से हल किया गया; अगर कोई दूसरा तरीका है तो कृपया मुझे बताएं, और मैं स्वीकृत उत्तर बदल दूंगा।

समाधान केवल उसी पोर्ट पर दो सॉकेट का उपयोग करने के लिए है; एक कच्चे, एक कच्चे नहीं:

import socket, select 
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s1.bind(('0.0.0.0', 1337)) 
s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP) 
s2.bind(('0.0.0.0', 1337)) 
while True: 
    r, w, x = select.select([s1, s2], [], []) 
    for i in r: 
     print i, i.recvfrom(131072) 

यह "गंतव्य तक नहीं पहुंचा जा" ICMP पैकेट चले जाओ बनाता है और बनाता है सभी पैकेट ठीक के माध्यम से जाना। मुझे लगता है कि ऑपरेटिंग सिस्टम बंदरगाह पर अच्छी तरह से जाने के लिए बंदरगाह पर एक गैर-कच्ची सॉकेट सुनना चाहता है, और फिर उसी बंदरगाह पर सुनने वाले किसी भी कच्चे सॉकेट को पैकेट की प्रतियां प्राप्त होंगी।

+0

रोचक द्वारा अग्रेषित किया जा रहा है, यह वास्तव में जानना बहुत अच्छा है! – brice

+0

यह वही था जो मैं ढूंढ रहा था! (हालांकि विंडोज़ के लिए जो थोड़ा अलग रॉ सॉकेट प्रारंभिकरण की आवश्यकता है) –