2014-06-09 23 views
8

Podczas łączenia się z serwerem z gniazdem klienta Java miałem dwa różne wyjątki limitu czasu połączenia.java.net.SocketTimeoutException kontra java.net.ConnectException

Caused by: java.net.SocketTimeoutException: connect timed out 
    at java.net.PlainSocketImpl.socketConnect(Native Method) 
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:381) 

Caused by: java.net.ConnectException: Connection refused: connect 
    at java.net.PlainSocketImpl.socketConnect(Native Method) 
    at java.net.PlainSocketImpl.doConnect(Unknown Source) 

sprawdziłem dokumentację ale SocketTimeoutException jest napisane, że „Sygnały, że limit czasu wystąpił na gnieździe czytać ani akceptować”, ale to nie jest sytuacja w moim przypadku. Ponieważ dostaję go podczas ustanawiania połączenia.

Jaka jest różnica między tymi dwoma wyjątkami? Właściwie spodziewałem się coraz ConnectException w jakikolwiek problem z połączeniem (firewall, port w dół, itd)

+0

Czy ustanowienie połączenia z gniazdem nie jest odczytywane ani akceptowane? – Raj

+0

@Raj Nie, jest to związane z * 'connect()' * lub 'accept().' Nie ma to nic wspólnego z 'read().' – EJP

+1

@EJP Tak, zgadzam się ale chodzi mi o to "Sygnały" że nastąpił timeout na gnieździe czytanym lub akceptowanym. " ale to nie jest situtaion w moim przypadku. "I starałem się przekazać Jeśli próbujesz się połączyć, to zaliczasz się do jednej kategorii, w tym przypadku nie czytaj, ale akceptuj – Raj

Odpowiedz

0

ConnectException jest wyrzucane na packet filter/firewall itp

SocketTimeoutException jest generowany, gdy masz ustawić określony limit czasu na swoje gniazdo i nie otrzymało niczego przed upływem limitu czasu.

Przykład z ServerSocket:

ServerSocket serverSocket = new ServerSocket... // Create server socket 
serverSocket.setSoTimeout(1000); 
serverSocket.accept(); 

Jeżeli ServerSocket nie otrzymał nic w ciągu 1000 ms będzie rzucać SocketTimeoutException. Należy zauważyć, że ten wyjątek jest zgłaszany dla wszystkich gniazd, które wykorzystują limity czasu, nie tylko ServerSocket. Oznacza to, że obiekt Socket, który rzuca SocketTimeoutException, nie ma niczego z powrotem z serwera wywoływanego przed upływem limitu czasu.

Aby rozwiązać ten problem, można albo upewnić się, że serwer reaguje szybciej, lub ustaw wyższą wartość limitu czasu.

+0

Oba te błędy występują po stronie klienta, gdy klient próbuje połączyć się z serwerem.Nie zaakceptuj lub odczytaj operację po mojej stronie, sprawdź śledzenie stosu: – cacert

+0

@cacert: Kiedy używasz gniazda z limitem czasu, a serwer nie odpowiada na żaden z twoich pakietów w określonym limicie czasu, wyrzuci wyjątek wyjątku sockettime. jawnie wywołać read lub accept, ale może się również zdarzyć podczas uzgadniania TCP.Jeżeli wystąpi przerwa w czasie uzgadniania (lub inicjalizacji gniazda), wyjątek jest zgłaszany w java.net.PlainSocketImpl.socketConnect (metoda natywna) :) – Pphoenix

+0

To oznacza, że ​​nie ustawiam limitu czasu połączenia w skarpecie klienta et, to dostanę ConnectException? – cacert

0

Będziesz uzyskać SocketTimeoutException jeśli określić limit czasu na connect(), lub jeśli już nazywany setSoTimeout() na Socket lub ServerSocket a read() lub accept() razy się odpowiednio. W przypadku connect(), jest to poważny problem: to, z czym próbujesz się połączyć, nie istnieje lub znajduje się za zaporą sieciową, a nie możesz stwierdzić, który z nich.

Dostaniesz connection refused jeśli peer aktywnie odmówił żądania połączenia, które zwykle oznacza, że ​​nie ma nic słuchania w porcie określonym. Zauważ, że w przeciwieństwie do limitu czasu, oznacza to, że otrzymana odpowiedź została odebrana i była ujemna.

+0

Więc jeśli otrzymam SocketTimeoutException, to jak mogę to zrozumieć, jeśli otrzymam go podczas komunikacji (podczas odczytu) lub nie mogę połączyć się z serwerem. – cacert

+0

@cacert Otrzymasz java.net.SocketTimeoutException: Czas oczekiwania na odczyt podczas komunikacji. – Raj

-1
Caused by: java.net.SocketTimeoutException: connect timed out 

Gdy nie można się połączyć z powodu niedostępności partnera. Twoje drugie pytanie, co z przeczytaniem? Niż dostaniesz

Caused by: java.net.SocketTimeoutException: Read timed out 

trzecia możliwość wzajemnej connection refused jeśli jest aktywny, ale odrzucił połączenie.

+0

Limity czasu połączenia nie są spowodowane przez nieaktywność węzła równorzędnego, ponieważ są one spowodowane przez nieaktywność * hosta * lub przeciwstawienie mu reguły zapory sieciowej; a jeśli peer jest aktywny, nie może odmówić połączenia. – EJP

2

również przyszedł tu szukając tym samym odpowiedź, pozornie the docs można łatwo błędnie interpretowane:

Łączy gniazdo do serwera o określonej wartości limitu czasu. Limit czasu równy zeru jest interpretowany jako nieskończony czas oczekiwania. Połączenie będzie blokować do momentu ustanowienia lub wystąpi błąd.

Kluczowym elementem, który przeoczyłem w tym jest „błąd” ... będzie the source widzę jak Java connect() faktycznie powołując Linux connect():

if (timeout <= 0) { 
    connect = connect(args...); 
    if (connect == -1 && errno == EINPROGRESS) { 
     connect = poll(args...); 
     // try again on EINTR 
    } 
} else { 
    // Go to non-blocking mode for a timeout. 
    connect = connect(args...); 

    if (connect!=0) { 
     // not EINPROGRESS? -> throw ConnectException 
     while (!connect || !error || timedout) { 
      connect = poll(args...); 
      // error/timedout handling 
     } 
     if (timedout) { 
      // throw SocketTimeoutException 
     } 
    } 
} 

/* report the appropriate exception */ 
if (error) { 
    //EINVAL; throw SocketException 
    //EINTR; throw InterruptedIOException 
    //EPROTO; throw ProtocolException 
    //ECONNREFUSED;ETIMEDOUT; throw ConnectException 
    //EHOSTUNREACH; throw NoRouteToHostException 
    //EADDRNOTAVAIL; throw NoRouteToHostException 
    //EISCONN, EBADF, other; throw SocketException 
} 

tj myślę SocketTimeoutException jest być wyrzucane, gdy sieć działa wolno, lub host nie reaguje w ogóle. Sprawdzając man connect, widzę, że ECCONNREFUSED musi zostać wyrzucony, gdy "nikt nasłuchujący na zdalnym adresie", tj. I ICMP nam tego nie mówi.

To oznacza, że ​​jeśli tak jak ja, staraliśmy się używać timeout podłączyć do gniazda (localhost), który nie był gotowy do podłączenia do, jesteś SOL'd.

Powiązane problemy