python mechanize/urllib2 силы, чтобы только использовать запросы?

Вот связанный вопрос, но я не мог выяснить, как применить ответ на 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.

11
задан Community 23 May 2017 в 10:31
поделиться

2 ответа

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
2
ответ дан 3 December 2019 в 04:32
поделиться

Нет ответа, а несколько данных данных. Разрешение 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.

4
ответ дан 3 December 2019 в 04:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: