2010-01-06 12 views
11

यहाँ एक संबंधित सवाल है, लेकिन मैं समझ नहीं सकता कैसे मशीनीकरण के लिए/urllib2 जवाब लागू करने के लिए: इस सरल कोड how to force python httplib library to use only A requestsफोर्स पायथन मैकेनाइजेशन/urllib2 केवल एक अनुरोध का उपयोग करने के लिए?

असल में, यह देखते हुए:

#!/usr/bin/python 
import urllib2 
print urllib2.urlopen('http://python.org/').read(100) 

यह wireshark निम्नलिखित कह में परिणाम है:

0.000000 10.102.0.79 -> 8.8.8.8  DNS Standard query A python.org 
    0.000023 10.102.0.79 -> 8.8.8.8  DNS Standard query AAAA python.org 
    0.005369  8.8.8.8 -> 10.102.0.79 DNS Standard query response A 82.94.164.162 
    5.004494 10.102.0.79 -> 8.8.8.8  DNS Standard query A python.org 
    5.010540  8.8.8.8 -> 10.102.0.79 DNS Standard query response A 82.94.164.162 
    5.010599 10.102.0.79 -> 8.8.8.8  DNS Standard query AAAA python.org 
    5.015832  8.8.8.8 -> 10.102.0.79 DNS Standard query response AAAA 2001:888:2000:d::a2 

एक 5 सेकंड की देरी है यही कारण है कि!

मेरे पास मेरे सिस्टम में कहीं भी आईपीवी 6 सक्षम नहीं है (gentoo USE=-ipv6 के साथ संकलित) इसलिए मुझे नहीं लगता कि पाइथन के पास आईपीवी 6 लुकअप भी करने का कोई कारण है।

उपर्युक्त संदर्भित प्रश्न ने सॉकेट प्रकार को AF_INET पर स्पष्ट रूप से सेट करने का सुझाव दिया जो बहुत अच्छा लगता है। मुझे नहीं पता कि मैं किसी भी सॉकेट का उपयोग करने के लिए urllib या मशीनीकरण को कैसे मजबूर करता हूं।

संपादित: मुझे पता है कि AAAA प्रश्नों मुद्दे हैं, क्योंकि अन्य एप्लिकेशन के साथ-साथ देरी था और जैसे ही मैंने IPv6 विकलांग के साथ कंपाइल किया, समस्या दूर चला गया ... को छोड़कर के लिए अजगर में जो अभी भी करता है एएएए अनुरोध।

+0

यहां भिन्न, अलग-अलग प्रदाताओं से जुड़े विभिन्न मशीनों पर समान। मैंने libwww-perl का सहारा लिया है और यह GET कमांड है - यह तुरंत सभी मशीनों पर काम करता है। –

उत्तर

2

DNS सर्वर 8.8.8.8 (Google DNS) python.org के एएएए के बारे में पूछे जाने पर तत्काल उत्तर देता है। इसलिए, तथ्य यह है कि हम आपके द्वारा पोस्ट किए गए ट्रेस में यह उत्तर नहीं देखते हैं, शायद यह इंगित करता है कि यह पैकेट वापस नहीं आया (जो यूडीपी के साथ होता है)। यदि यह नुकसान यादृच्छिक है, तो यह सामान्य है। यदि यह व्यवस्थित है, तो इसका मतलब है कि आपके नेटवर्क सेटअप में कोई समस्या है, एक टूटी हुई फ़ायरवॉल हो सकती है जो पहले एएएए जवाब को वापस आने से रोकती है।

5-सेकंड की देरी आपके स्टब रिज़ॉल्वर से आता है। उस स्थिति में, यदि यह यादृच्छिक है, तो शायद यह दुर्भाग्यपूर्ण है, लेकिन आईपीवी 6 से संबंधित नहीं है, एक रिकॉर्ड के लिए जवाब भी असफल हो सकता था।

आईपीवी 6 को अक्षम करना एक बहुत ही अजीब कदम लगता है, अंतिम आईपीवी 4 पता वितरित होने से केवल दो साल पहले!

% dig @8.8.8.8 AAAA python.org 

; <<>> DiG 9.5.1-P3 <<>> @8.8.8.8 AAAA python.org 
; (1 server found) 
;; global options: printcmd 
;; Got answer: 
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50323 
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 

;; OPT PSEUDOSECTION: 
; EDNS: version: 0, flags:; udp: 512 
;; QUESTION SECTION: 
;python.org.     IN  AAAA 

;; ANSWER SECTION: 
python.org.    69917 IN  AAAA 2001:888:2000:d::a2 

;; Query time: 36 msec 
;; SERVER: 8.8.8.8#53(8.8.8.8) 
;; WHEN: Sat Jan 9 21:51:14 2010 
;; MSG SIZE rcvd: 67 
+0

अच्छी तरह से, मुझे आईपीवी 6 का उपयोग करने में खुशी होगी ... एक बार जब यह मेरे DNS प्रश्नों में 5 सेकंड देरी जोड़ता है :- पी। और दुर्भाग्य से, यह "दुर्भाग्य" नहीं है यह हर एक प्रश्न है। –

4

कोई जवाब नहीं, लेकिन कुछ डेटापॉइंट्स।

for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): 
    af, socktype, proto, canonname, sa = res 
    self.sock = socket.socket(af, socktype, proto) 
    try: 
     self.sock.connect(sa) 
    except socket.error, msg: 
     continue 
    break 

क्या हो रहा है पर कुछ टिप्पणियाँ::

DNS रिज़ॉल्यूशन

कोड प्रवाह मोटे तौर पर है (मेरे अजगर 2.5.4 stdlib पर लाइन 670) HTTPConnection.connect() में httplib.py से होने वाले प्रतीत होता है

  • socket.getaddrinfo() पर तीसरा तर्क सॉकेट परिवारों को सीमित करता है - यानि, आईपीवी 4 बनाम आईपीवी 6। पास करने से सभी परिवारों को रिटर्न मिलता है। शून्य stdlib में हार्डकोड किया गया है।

  • getaddrinfo() में होस्टनाम पास करने से नाम रिज़ॉल्यूशन होगा - आईएसवी 6 सक्षम के साथ मेरे ओएस एक्स बॉक्स पर, ए और एएएए रिकॉर्ड दोनों बाहर निकलते हैं, दोनों जवाब सही वापस आते हैं और दोनों वापस आते हैं।

  • कनेक्ट पाश के बाकी प्रत्येक लौटे पते की कोशिश करता है जब तक कि एक

उदाहरण के लिए सफल होता है:

>>> socket.getaddrinfo("python.org", 80, 0, socket.SOCK_STREAM) 
[ 
(30, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0)), 
(2, 1, 6, '', ('82.94.164.162', 80)) 
] 
>>> help(socket.getaddrinfo) 
getaddrinfo(...) 
    getaddrinfo(host, port [, family, socktype, proto, flags]) 
     -> list of (family, socktype, proto, canonname, sockaddr) 

कुछ अनुमान:

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

  • पायथन सॉकेट मॉड्यूल पॉज़िक्स सॉकेट एपीआई के चारों ओर एक पतला आवरण है; I की उम्मीद है कि वे सिस्टम पर कॉन्फ़िगर किए गए प्रत्येक परिवार को & उपलब्ध कर रहे हैं। जेनेटू की आईपीवी 6 कॉन्फ़िगरेशन को दोबारा जांचें।

+0

मुझे लगता है कि पाइथन को 's'.getaddrinfo' को' 0' पास नहीं करना चाहिए यदि यह कोई ipv6 समर्थन के साथ बनाया गया है। शायद इसे कुछ तरीकों से मामूली बग माना जा सकता है। –

15

एक ही समस्या से पीड़ित, यहां जे.जे. द्वारा दी गई जानकारी के आधार पर एक बदसूरत हैक (अपने जोखिम पर उपयोग करें ..) है। ।

यह मूलतः बलों socket.getaddrinfo(..) बजाय socket.AF_UNSPEC (शून्य है, जो है क्या socket.create_connection में इस्तेमाल किया जा रहा है) का उपयोग करने का socket.AF_INET के family पैरामीटर, न केवल urllib2 से कॉल के लिए, लेकिन यह socket.getaddrinfo(..) के लिए सभी कॉल के लिए क्या करना चाहिए:

#-------------------- 
# do this once at program startup 
#-------------------- 
import socket 
origGetAddrInfo = socket.getaddrinfo 

def getAddrInfoWrapper(host, port, family=0, socktype=0, proto=0, flags=0): 
    return origGetAddrInfo(host, port, socket.AF_INET, socktype, proto, flags) 

# replace the original socket.getaddrinfo by our version 
socket.getaddrinfo = getAddrInfoWrapper 

#-------------------- 
import urllib2 

print urllib2.urlopen("http://python.org/").read(100) 

यह कम से कम इस साधारण मामले में मेरे लिए काम करता है।

+0

अभी परीक्षण किया गया है, अभी भी पाइथन 3.5.2 में निर्दोष रूप से काम करता है। – Rich

2

इसका सबसे अधिक संभावित कारण broken egress firewall है। जूनियर फ़ायरवॉल इसका कारण बन सकता है, उदाहरण के लिए, हालांकि उनके पास workaround उपलब्ध है।

यदि आप फ़ायरवॉल को ठीक करने के लिए अपने नेटवर्क व्यवस्थापक नहीं प्राप्त कर सकते हैं, तो आप होस्ट-आधारित वर्कअराउंड को आजमा सकते हैं। अपने /etc/resolv.conf को यह पंक्ति जोड़ दें:

options single-request-reopen 

आदमी पेज यह अच्छी तरह से बताते हैं:

रिसोल्वर एक और AAAA अनुरोधों के लिए एक ही सॉकेट का उपयोग करता है। कुछ हार्डवेयर गलती से केवल एक जवाब भेजता है। जब ऐसा होता है तो ग्राहक sytem बैठेगा और दूसरे जवाब की प्रतीक्षा करेंगे। इस विकल्प को इस व्यवहार को बदलने पर चालू करना ताकि यदि एक ही बंदरगाह से दो अनुरोध सही तरीके से संभाले नहीं जाए तो यह सॉकेट बंद कर देगा और दूसरा अनुरोध भेजने से पहले एक नया खोल देगा।

+0

धन्यवाद इसने आईपीवी 6 नाम संकल्प segfault समस्या तय की है जिसमें मैं अजगर में था। – jan

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

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