强制python mechanize/urllib2只使用A请求?

Eva*_*ran 11 python mechanize urllib ipv6

这是一个相关的问题,但我无法弄清楚如何应用mechanize/urllib2的答案:如何强制python httplib库只使用A请求

基本上,给出这个简单的代码:

#!/usr/bin/python
import urllib2
print urllib2.urlopen('http://python.org/').read(100)
Run Code Online (Sandbox Code Playgroud)

这导致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
Run Code Online (Sandbox Code Playgroud)

这是一个5秒的延迟!

我的系统中没有启用IPv6(gentoo编译USE=-ipv6)所以我不认为python有任何理由甚至尝试IPv6查找.

上面引用的问题建议明确设置AF_INET听起来很棒的套接字类型.我不知道如何强制urllib或机械化使用我创建的任何套接字.

编辑:我知道AAAA查询是问题,因为其他应用程序也有延迟,一旦我禁用ipv6重新编译,问题就消失了......除了仍在执行AAAA请求的python中.

And*_*ner 16

遇到同样的问题,根据JJ提供的信息,这是一个丑陋的黑客(使用风险自负......).

这基本上强制family的参数socket.getaddrinfo(..),以socket.AF_INET代替使用socket.AF_UNSPEC(零,这似乎是在使用socket.create_connection),不仅从通话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)
Run Code Online (Sandbox Code Playgroud)

至少在这个简单的情况下,这对我有用.


bor*_*yer 2

当询问 python.org 的 AAAA 时,DNS 服务器 8.8.8.8(Google DNS)立即回复。因此,事实上我们在您发布的跟踪中没有看到此回复,这可能表明此数据包没有返回(UDP 会发生这种情况)。如果这种损失是随机的,那么这是正常的。如果是系统性的,则意味着您的网络设置存在问题,可能是防火墙损坏,导致第一个 AAAA 回复无法返回。

5 秒的延迟来自存根解析器。那么,如果是随机的,可能是运气不好,但与 IPv6 无关,A 记录的回复也可能失败。

禁用 IPv6 似乎是一个非常奇怪的举动,距离最后一个 IPv4 地址分配只有两年!

% 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
Run Code Online (Sandbox Code Playgroud)