2014-11-09 27 views
7

Mam następujący kod do pracy ciągłej pętli przynieść pewne treści ze strony internetowej:Python3 urllib.request nie zamknie połączenia natychmiast

from http.cookiejar import CookieJar 
from urllib import request 

cj = CookieJar() 
cp = request.HTTPCookieProcessor(cj) 
hh = request.HTTPHandler() 
opener = request.build_opener(cp, hh) 

while True: 
    # build url 
    req = request.Request(url=url) 
    p = opener.open(req) 
    c = p.read() 
    # process c 
    p.close() 
    # check for abort condition, or continue 

Treści są prawidłowo odczytać. Ale z jakiegoś powodu połączenia TCP nie zostaną zamknięte. Obserwuję aktywną liczbę połączeń z interfejsu routera dd-wrt i stale rośnie. Jeśli skrypt będzie nadal działał, spowoduje to wyczerpanie limitu 4096 połączenia routera. Gdy tak się stanie, skrypt po prostu przejdzie w stan oczekiwania (router nie zezwoli na nowe połączenia, ale limit czasu jeszcze nie dotarł). Po kilku minutach połączenia te zostaną zamknięte i skrypt zostanie wznowiony.

Udało mi się zaobserwować stan tych wiszących połączeń z routera. Mają ten sam stan: TIME_WAIT.

Spodziewam się, że ten skrypt będzie używał jednocześnie więcej niż 1 połączenia TCP. Co ja robię źle?

Używam Python 3.4.2 na Mac OS X 10.10.

+1

Może to pomóc: http://stackoverflow.com/questions/5442291/close-urllib2-connection – Eric

Odpowiedz

4

Dzięki pewnym badaniom odkryłem przyczynę tego problemu: the design of TCP protocol. W skrócie, gdy się rozłączysz, połączenie nie zostanie natychmiast przerwane, przejdzie w stan "TIME_WAIT" i upłynie po 4 minutach. W przeciwieństwie do tego, czego się spodziewałem, połączenie nie znika natychmiast.

Według this question, nie można również skutecznie zrzucić połączenia (bez restartowania stosu sieciowego).

Okazuje się, że w moim przypadku, np. this question stated, lepszym rozwiązaniem byłoby użycie stałego połączenia, a.k.a. HTTP keep-alive. Ponieważ wysyłam zapytanie do tego samego serwera, to zadziała.