Ustawianie limitu czasu dla operacji gniazda

86

Kiedy tworzę gniazdo:

Socket socket = new Socket(ipAddress, port);

Zgłasza wyjątek, który jest OK, ponieważ adres IP jest niedostępny. (Zmienne testowe, gdzie String ipAddress = "192.168.0.3"i int port = 300.)

Problem jest następujący: jak ustawić limit czasu dla tego gniazda?

Kiedy tworzę gniazdo, jak mogę skrócić czas, zanim otrzymam a UnknownHostExceptioni przekroczę limit czasu gniazda?

Jennifer
źródło
10
@adrianboimvaser: W takim przypadku powinieneś oznaczyć jako duplikat i zostawić komentarz wskazujący na duplikat, aby moderator mógł go zamknąć jako taki (zostawiłeś ten komentarz rok temu - być może już to wiesz). Oddałbym głos za zrobienie tego teraz, ale nie mam pojęcia, gdzie jest duplikat!
Tom Anderson
1
Aby kontynuować tendencję do odpowiadania z opóźnieniem lat, @EJP tytuł tego pytania jest znacznie mniej niejednoznaczny niż sugerowany przez ciebie duplikat
Izaak
@Isaac I tak naprawdę to wcale nie jest duplikat, komentarz wycofany.
Markiz Lorne
(Uwaga: poprawiłem tytuł, aby był mniej niejednoznaczny.)
Stephen C

Odpowiedzi:

165

Zamiast tego użyj Socket()konstruktora i connect(SocketAddress endpoint, int timeout)metody .

W twoim przypadku wyglądałoby to mniej więcej tak:

Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, port), 1000);

Cytat z dokumentacji

connect

public void connect(SocketAddress endpoint, int timeout) throws IOException

Łączy to gniazdo z serwerem z określoną wartością limitu czasu. Limit czasu równy zero jest interpretowany jako nieskończony limit czasu. Połączenie będzie wtedy blokowane do czasu ustanowienia lub wystąpienia błędu.

Parametry:

endpoint- the SocketAddress
timeout- wartość limitu czasu, która ma być używana w milisekundach.

Rzuty:

IOException- jeśli wystąpi błąd podczas połączenia
SocketTimeoutException- jeśli upłynie limit czasu przed połączeniem
IllegalBlockingModeException- jeśli to gniazdo ma skojarzony kanał, a kanał jest w trybie nieblokującym
IllegalArgumentException- jeśli punkt końcowy ma wartość null lub jest podklasą SocketAddress nieobsługiwaną przez to gniazdo

Od: 1.4

aioobe
źródło
4
Może to skrócić limit czasu dla ConnectException (ale nie zwiększyć go) i nie ma wpływu na limit czasu dla UnknownHostException, który, jak twierdzi OP, otrzymuje (chociaż nie wierzę w to). Należy również zauważyć, że Javadoc błędnie stwierdza, że ​​wartością domyślną jest nieskończoność. Tak nie jest. Platforma ma domyślny limit czasu wynoszący około minuty i nie można go zwiększyć.
Markiz Lorne
3
Nawet po 4 latach było to pomocne, to powinna być akceptowana odpowiedź.
Sharp Edge
4
Jest już po 5 latach i jest to najlepsza odpowiedź, jaką znalazłem w Internecie. Dziękuję
MBH
1
Ważne jest również, aby wywołać socket.setSoTimeout(timeoutMillis)przekroczenie limitu czasu podczas blokowania operacji we / wy.
Gray
43

Nie ustawiasz limitu czasu dla gniazda, ustawiasz limit czasu dla operacji wykonywanych na tym gnieździe.

Na przykład socket.connect(otherAddress, timeout)

Lub socket.setSoTimeout(timeout)do ustawiania limitu czasu read()operacji.

Zobacz: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html

payne
źródło
Cóż, w tym przypadku jest to również operacja łączenia. Nie mogę znaleźć żadnego miejsca, które stwierdza, że ​​ten ctor używa nieskończonego limitu czasu, chociaż wydaje się, że tak jest.
sandos
3
@sandos Jest to jasno określone w Javadoc dla connect (). Jednak jest to również błędne. Domyślnym limitem czasu jest limit czasu platformy, około minuty, a nie nieskończoność, i można go skrócić tylko za pomocą tej metody connect (), a nie zwiększyć.
Markiz Lorne
uwaga, socket.setSoTimeoutmusi zostać wywołane PO connect, w przeciwnym razie nie będzie miało żadnego efektu i odczyty nigdy nie przekroczą limitu czasu. jest to jeden słabo udokumentowany problem.
pstanton
19

Możesz użyć następującego rozwiązania:

SocketAddress sockaddr = new InetSocketAddress(ip, port);
// Create your socket
Socket socket = new Socket();
// Connect with 10 s timeout
socket.connect(sockaddr, 10000);

Mam nadzieję, że to pomoże!

rafa
źródło
1
Jeśli, jak twierdzi, otrzyma wyjątek UnknownHostException, nastąpi to w pierwszym wierszu, w którym nie obowiązuje zmodyfikowany limit czasu.
Markiz Lorne
Jednak pierwsza linia nie zgłasza żadnego wyjątku. Z dokumentacji: „Próba będzie rozwiązać nazwę hosta do wiadomości InetAddress Jeśli ta próba się nie powiedzie, adres zostanie oznaczony jako nierozwiązany.”
ady
W takim przypadku problem zostanie rozwiązany connect()metodą, ale nie pod kontrolą limitu czasu.
Markiz Lorne
8

Nie możesz kontrolować limitu czasu z powodu UnknownHostException. To są czasy DNS. Możesz kontrolować limit czasu połączenia tylko pod warunkiem posiadania prawidłowego hosta. Żadna z poprzednich odpowiedzi nie odnosi się poprawnie do tego punktu.

Ale trudno mi uwierzyć, że naprawdę otrzymujesz UnknownHostExceptionadres IP, a nie nazwę hosta.

EDYCJA Aby kontrolować limity czasu DNS Javy, zobacz tę odpowiedź .

Markiz Lorne
źródło