Impostazione di un timeout per le operazioni sui socket


86

Quando creo un socket:

Socket socket = new Socket(ipAddress, port);

Genera un'eccezione, che va bene, perché l'indirizzo IP non è disponibile. (Le variabili di test dove String ipAddress = "192.168.0.3"e int port = 300.)

Il problema è: come imposto il timeout per quel socket?

Quando creo il socket, come faccio a ridurre il tempo prima di ottenere un UnknownHostExceptione ottenere il timeout del socket?


10
@adrianboimvaser: in tal caso, dovresti contrassegnare come duplicato e lasciare un commento che punta al duplicato, in modo che un moderatore possa chiuderlo come tale (hai lasciato quel commento un anno fa - forse lo sai ormai). Vorrei esprimere il mio voto per farlo ora, ma non ho idea di dove sia il duplicato!
Tom Anderson

1
Per continuare la tendenza a rispondere con anni di ritardo, @EJP il titolo di questa domanda è molto meno ambiguo del duplicato che hai suggerito
Isaac

@ Isaac E in effetti non è affatto un duplicato, commento ritirato.
Marchese di Lorne,

(Nota: ho modificato il titolo per essere meno ambiguo.)
Stephen C

Risposte:


165

Usa invece il Socket()costruttore e il connect(SocketAddress endpoint, int timeout)metodo .

Nel tuo caso sarebbe simile a:

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

Citando dalla documentazione

connect

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

Connette questo socket al server con un valore di timeout specificato. Un timeout pari a zero viene interpretato come un timeout infinito. La connessione verrà quindi bloccata fino a quando non viene stabilita o si verifica un errore.

Parametri:

endpoint- SocketAddress
timeout- il valore di timeout da utilizzare in millisecondi.

Lanci:

IOException- se si verifica un errore durante la connessione
SocketTimeoutException- se il timeout scade prima della connessione
IllegalBlockingModeException- se questo socket ha un canale associato e il canale è in modalità non bloccante
IllegalArgumentException- se l'endpoint è nullo o è una sottoclasse SocketAddress non supportata da questo socket

Dal: 1.4


4
Ciò può ridurre il timeout per ConnectException (ma non aumentarlo) e non ha alcun effetto sul timeout per UnknownHostException, che l'OP afferma di ottenere (anche se non ci credo). Notare anche che Javadoc non è corretto nell'affermare che l'impostazione predefinita è infinito. Non lo è. La piattaforma ha un timeout predefinito di circa un minuto e non può essere aumentato.
Marchese di Lorne

3
Anche dopo 4 anni questo è stato utile, questa dovrebbe essere la risposta accettata.
Sharp Edge

4
Sono passati 5 anni ed è la migliore risposta che ho trovato su Internet .. Grazie
MBH

1
È anche importante chiamare i socket.setSoTimeout(timeoutMillis)timeout durante il blocco delle operazioni di I / O.
Grey

43

Non imposti un timeout per il socket, imposti un timeout per le operazioni che esegui su quel socket.

Per esempio socket.connect(otherAddress, timeout)

O socket.setSoTimeout(timeout)per impostare un timeout sulle read()operazioni.

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


Ebbene, in questo caso è anche un'operazione, connettere. Non riesco a trovare alcun posto che affermi che questo ctor utilizza un timeout infinito anche se sembra essere il caso.
sandos

3
@sandos È chiaramente indicato nel Javadoc per connect (). Tuttavia è anche sbagliato. Il timeout predefinito è il timeout della piattaforma, circa un minuto, non infinito, e può essere ridotto solo con questo metodo connect (), non aumentato.
Marchese di Lorne

nota, socket.setSoTimeoutdeve essere chiamato DOPO connect, altrimenti non avrà alcun effetto e le letture non scadranno mai. questo è un trucco scarsamente documentato.
pstanton

19

Puoi usare la seguente soluzione:

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

Spero che sia d'aiuto!


1
Se, come afferma, riceve un'eccezione UnknownHostException, accadrà sulla prima riga, dove non è attivo alcun timeout modificato.
Marchese di Lorne

Tuttavia, la prima riga non genera alcuna eccezione. Dalla documentazione: "Verrà effettuato un tentativo di risolvere il nome host in un InetAddress. Se il tentativo fallisce, l'indirizzo verrà contrassegnato come irrisolto"
ady

In tal caso verrà risolto con il connect()metodo, ma non sotto il controllo di un timeout.
Marchese di Lorne

8

Non puoi controllare il timeout a causa di UnknownHostException. Questi sono i tempi DNS. È possibile controllare il timeout di connessione solo con un host valido. Nessuna delle risposte precedenti affronta questo punto correttamente.

Ma trovo difficile credere che tu stia davvero ricevendo un UnknownHostException quando specifichi un indirizzo IP piuttosto che un nome host.

MODIFICA Per controllare i timeout DNS di Java, vedere questa risposta .


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.