2012-12-24 15 views
10

Napisałem program, który otwiera httpurlconnection do strony internetowej poprzez losowe proxy. Mój httpurlconnection nazywa się conn. Teraz wiem, że niektóre z tych serwerów proxy mogą być zbyt wolne, więc ustawiłem limit czasu połączenia na 40000 milisekund z conn.setConnectTimeout(40000) i conn.setReadTimeout(40000).Limit czasu HTTPUrlConnection Java nie działa

Po robią tak, mam ten kod:

long diff = 0; 
    long starttime = 0; 
    long endtime = 0; 

    try 
    { 
     starttime = System.currentTimeMillis(); 
     conn.connect(); 

     endtime = System.currentTimeMillis(); 

     diff = endtime - starttime; 

     if (endtime <= starttime + conn.getConnectTimeout()) 
     { 
      //Trying to read sourecode 
      InputStreamReader isrConn = new InputStreamReader(conn.getInputStream()); 
      BufferedReader brConn = new BufferedReader(isrConn); 

      line = brConn.readLine(); 

      while (line != null) 
      { 

       response += line + "\t"; 
       try 
       { 
        line = brConn.readLine(); 
       } catch (IOException e) 
       { 
        printError("Reading sourcecode failed."); 
       } 

      } 
     } 
     else 
     { 
      response = "blabla."; 
     } 




    // If conn.connect failed 
    } catch (IOException e) 
    { 
     endtime = System.currentTimeMillis(); 
     diff = endtime - starttime; 

     response = "Message: "+e.getMessage() +" MyTimeout:"+ conn.getConnectTimeout() +" Actual time passed: "+ diff; 
       e.printStackTrace(); 


    } 

Istnieją powody, dla których połączenie może zawodzić, więc w wielu przypadkach i dostać się do ostatniego bloku catch i pojawia się następujący komunikat:


Wiadomość: Connection timed out: connect MyTimeout: 40000 Rzeczywisty czas przeszły: 21012

Wiadomość: Connection timed out: connect MyTimeout: 40000 Rzeczywisty czas przeszły: 21016

Wiadomość: Connection timed out: connect MyTimeout: 40000 Rzeczywisty czas przeszły: 21010

Wiadomość: Connection timed out: connect MyTimeout: 40000 Rzeczywisty czas przeszły: 21009


Więc moje pytanie byłoby : Ustawiłem limit czasu na 40000 milisekund, ale dostaję odpowiedź "Limit czasu połączenia" po około 21000 milisekund, czy ktoś z was wie, dlaczego tak jest?

EDYCJA: im przy użyciu systemu Windows 7 i teraz dodałem e.printStackTrace() do catch-bloku, jak powiedział w komentarzach. dzięki jak dotąd. wyjście jest teraz (przykład):

java.net.ConnectException: Connection timed out: connect 
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) 
    at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) 
    at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) 
    at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) 
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source) 
    at java.net.PlainSocketImpl.connect(Unknown Source) 
    at java.net.Socket.connect(Unknown Source) 
    at sun.net.NetworkClient.doConnect(Unknown Source) 
    at sun.net.www.http.HttpClient.openServer(Unknown Source) 
    at sun.net.www.http.HttpClient$1.run(Unknown Source) 
    at sun.net.www.http.HttpClient$1.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.net.www.http.HttpClient.privilegedOpenServer(Unknown Source) 
    at sun.net.www.http.HttpClient.openServer(Unknown Source) 
    at sun.net.www.http.HttpClient.<init>(Unknown Source) 
    at sun.net.www.http.HttpClient.New(Unknown Source) 
    at sun.net.www.http.HttpClient.New(Unknown Source) 
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source) 
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source) 
    at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source) 
    at TestThread.getSourcePage(TestThread.java:361) 
    at TestThread.aChecker(TestThread.java:216) 
    at TestThread.getNextProxy(TestThread.java:169) 
    at TestThread.getNextC(TestThread.java:157) 
    at TestThread.aChecker(TestThread.java:273) 
    at TestThread.getNextProxy(TestThread.java:169) 
    at TestThread.aChecker(TestThread.java:295) 
    at TestThread.getNextProxy(TestThread.java:169) 
    at TestThread.getNextC(TestThread.java:157) 
    at TestThread.run(TestThread.java:103) 
    at java.lang.Thread.run(Unknown Source) 

Message: Connection timed out: connect MyTimeout:40000 Actual time passed: 21015 
+3

wyjście i proszę pisać rzeczywisty ślad stosu zamiast własnych wiadomości. –

+1

może to być zależne od systemu operacyjnego, proszę określić, który system operacyjny jest tym –

+0

Jak wspomniano przez Briana Roacha, proszę opublikować wyjście z 'e.printStackTrace()' w bloku catch. –

Odpowiedz

6

Z mojego doświadczenia wynika, że ​​HttpUrlConnection nie przekroczy limitu czasu podczas rozpoznawania nazw. Jeśli Twoje urządzenie zapisało adres docelowy w pamięci podręcznej, to zostanie ono ustawione poprawnie.

Do celów testowych użyj swojego adresu IP w swoim kodzie.

Zwykle dzieje się to na urządzeniach mobilnych.

10

Spójrz na wyjątku masz:
Największy pojęcia: Otrzymujesz java.net.ConnectException zgodnie javadoc, java.net.ConnectException oznacza, że ​​połączenie zostało odrzucone zdalnie z powodów takich jak proces nie nasłuchuje na porcie.

public class ConnectException 
extends SocketException 

Signals that an error occurred while attempting to connect a socket to a remote address and port. 
Typically, the connection was refused remotely (e.g., no process is listening on the remote 
address/port) 

Co skonfigurowano w HttpURLConnection:
Limit czasu dla połączenia (biorąc pod uwagę, że port zdalny akceptuje połączenia). Jeśli upłynie limit czasu połączenia, otrzymasz numer java.net.SocketTimeoutException, a nie java.net.ConnectException.

Co zatem powoduje java.net.ConnectException?
Próbowałem następujących testów:

+------------+------------+----------------+------------------+---------------------------------+ 
    | Valid Host | Valid Port | Valid Proxy IP | Valid Proxy Port | Exception      | 
    +------------+------------+----------------+------------------+---------------------------------+ 
#1 | yes  | yes  | -NA-   | -NA-    | -- none --      | 
#2 | yes  | no   | -NA-   | -NA-    | java.net.ConnectException  | 
    +------------+------------+----------------+------------------+---------------------------------+ 
#3 | yes  | yes  | yes   | yes    | -- none --      | 
#4 | yes  | no   | yes   | yes    | java.net.SocketTimeoutException | 
#5 | yes  | yes  | yes   | no    | java.net.ConnectException  | 
    +------------+------------+----------------+------------------+---------------------------------+ 
  • Case # 1, # 3 są szczęśliwy ścieżki, w którym wszystkie configs są poprawne
  • W przypadku # 4, otrzymujemy java.net.SocketTimeoutException ponieważ proces java jest w stanie nawiązać połączenie (do portu proxy), ale nie otrzymuje żadnych danych do odczytania, ponieważ numer portu hosta docelowego jest nieprawidłowy
  • W przypadku # 2, # 5 otrzymujemy java.net.ConnectException, ponieważ port, w którym próbuje się pisać w java/odczyt jest nieprawidłowy
  • Wartość limitu czasu połączenia nie jest odpowiednia w przypadku, gdy żaden proces nie nasłuchuje na porcie, z którym próbuje się połączyć proces java. Dlatego masz ConnectException przed przeterminowanie

Message: Connection refused: connect MyTimeout:10000 Actual time passed: 6549 java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) .... ....

Wniosek:

  • Niektóre serwery proxy starasz się połączyć, musi być w dół. Stąd proces java rzucił java.net.ConnectException
  • Lepiej złapać java.net.ConnectException i oznaczyć jako nieprawidłowe proxy/dół