Вот связанный вопрос, но я не мог выяснить, как применить ответ на mechanize/urllib2: как вынудить Python httplib библиотека использовать только запрос
В основном, учитывая этот простой код:
#!/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-секундная задержка!
Мне не включили IPv6 нигде в моей системе (хинду, скомпилированный с USE=-ipv6
) таким образом, я не думаю, что Python имеет любую причину даже попробовать поиск IPv6.
Вышеупомянутый вопрос, предложенный, явно устанавливая сокет, вводит к AF_INET
который звучит великолепно. Я понятия не имею, как вызвать urllib или механизировать для использования любых сокетов, которые я создаю все же.
Править: Я знаю, что запросы AAAA являются проблемой, потому что другие приложения имели задержку также и как только я перекомпилировал с отключенным ipv6, проблема ушла... за исключением в Python, который все еще выполняет запросы AAAA.
DNS-сервер 8.8.8.8 (Google DNS) отвечает немедленно, когда его спрашивают о AAAA Of Python.org. Поэтому тот факт, что мы не видим этого ответа в трассировке, которую вы пост, вероятно, указывают, что этот пакет не вернулся (что происходит с UDP). Если эта потеря случайна, это нормально. Если это систематически, это означает, что в вашей сетевой настройке есть проблема, может быть сломанным брандмауэром, который предотвращает возвращение первого ответа AAAA.
5-секунда задержка исходит от вашего расстройки. В этом случае, если это случайно, это, вероятно, невезение, но не связано с IPv6, ответ для записи также может потерпеть неудачу.
Отключение 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
Нет ответа, а несколько данных данных. Разрешение DNS, по-видимому, происходит из httplib.py
в httpConnection.connect ()
(строка 670 на моем Python 2.5.4 STDLIB)
Поток кода примерно:
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
Несколько комментариев по поводу того, что происходит:
Третий аргумент на Socket.getAddrinfo ()
ограничивает семейства сокетов - IE, IPv4 против IPv6. Прохождение ноль возвращает все семьи. Ноль жестко определяется в Stdlib.
Прохождение имени хоста в GetAddrinfo ()
приведет к тому, что разрешение имени - на моей коробке OS X с включенным IPv6, как записи A и AAAA, оба ответа возвращаются, и оба возвращаются.
Остальная часть цикла Connect пытается каждый возвращенный адрес до тех пор, пока не будет успешно
, например:
>>> 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 ()
жестко определяется до нуля, Вы не сможете переопределить записи по VS. AAAA через некоторые поддерживаемые интерфейс API в Urllib. Если механизация не имеет своего собственного разрешения имени по какой-то другой причине, механизация не может. С конструкции контура Connect это по дизайну.
Модуль сокета Python является тонкой оберткой вокруг APIS-гнезда POSIX; I ожидается Они разрешают каждую семью, доступную и настроенную в системе. Дважды проверьте конфигурацию Gentoo's IPv6.