Establecer un tiempo de espera para operaciones de socket

86

Cuando creo un socket:

Socket socket = new Socket(ipAddress, port);

Lanza una excepción, que está bien, porque la dirección IP no está disponible. (Las variables de prueba donde String ipAddress = "192.168.0.3"y int port = 300.)

El problema es: ¿cómo configuro el tiempo de espera para ese socket?

Cuando creo el socket, ¿cómo puedo reducir el tiempo antes de obtener un UnknownHostExceptionsocket y obtener el tiempo de espera?

Jennifer
fuente
10
@adrianboimvaser: En ese caso, debes marcar como duplicado y dejar un comentario que apunte al duplicado, para que un moderador pueda cerrarlo como tal (dejaste ese comentario hace un año, tal vez ya lo sepas). Daría mi voto por hacer eso ahora, ¡pero no tengo idea de dónde está el duplicado!
Tom Anderson
1
Para continuar la tendencia de responder con años de retraso, @EJP, el título de esta pregunta es mucho menos ambiguo que el duplicado que sugirió
Isaac
@Isaac Y de hecho no es un duplicado en absoluto, se retractó del comentario.
Marqués de Lorne
(Nota: he modificado el título para que sea menos ambiguo).
Stephen C

Respuestas:

165

Utilice el Socket()constructor y el connect(SocketAddress endpoint, int timeout)método en su lugar.

En su caso, se vería así:

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

Citando de la documentación

connect

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

Conecta este socket al servidor con un valor de tiempo de espera especificado. Un tiempo de espera de cero se interpreta como un tiempo de espera infinito. La conexión se bloqueará hasta que se establezca o se produzca un error.

Parámetros:

endpoint- SocketAddress
timeout: el valor de tiempo de espera que se utilizará en milisegundos.

Lanza:

IOException- si ocurre un error durante la conexión
SocketTimeoutException- si el tiempo de espera expira antes de la conexión
IllegalBlockingModeException- si este socket tiene un canal asociado y el canal está en modo sin bloqueo
IllegalArgumentException- si el punto final es nulo o es una subclase de SocketAddress no admitida por este socket

Desde: 1.4

aioobe
fuente
4
Esto puede reducir el tiempo de espera para ConnectException (pero no aumentarlo), y no tiene ningún efecto en el tiempo de espera para UnknownHostException, que el OP afirma que está obteniendo (aunque no lo creo). Tenga en cuenta también que el Javadoc es incorrecto al afirmar que el valor predeterminado es infinito. No lo es. La plataforma tiene un tiempo de espera predeterminado de alrededor de un minuto y no se puede aumentar.
Marqués de Lorne
3
Incluso después de 4 años esto fue útil, esta debería ser la respuesta aceptada.
Sharp Edge
4
Han pasado 5 años y es la mejor respuesta que encontré en Internet. Gracias
MBH
1
También es importante solicitar socket.setSoTimeout(timeoutMillis)tiempos de espera durante el bloqueo de operaciones de E / S.
Gray
43

No establece un tiempo de espera para el socket, establece un tiempo de espera para las operaciones que realiza en ese socket.

Por ejemplo socket.connect(otherAddress, timeout)

O socket.setSoTimeout(timeout)para establecer un tiempo de espera en las read()operaciones.

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

Payne
fuente
Bueno, en este caso también es una operación, conectar. No puedo encontrar ningún lugar que indique que este ctor usa un tiempo de espera infinito, aunque ese parece ser el caso.
Sandos
3
@sandos Está claramente establecido en el Javadoc para connect (). Sin embargo, también es incorrecto. El tiempo de espera predeterminado es el tiempo de espera de la plataforma, alrededor de un minuto, no infinito, y solo se puede reducir con este método connect (), no aumentar.
Marqués de Lorne
nota, socket.setSoTimeoutdebe llamarse DESPUÉS connect, o no tendrá ningún efecto y las lecturas nunca se agotarán. este es un problema mal documentado.
pstanton
19

Podría utilizar la siguiente solución:

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

¡Espero eso ayude!

arrecife
fuente
1
Si, como afirma, obtiene una UnknownHostException, sucederá en la primera línea, donde no hay ningún tiempo de espera modificado en efecto.
Marqués de Lorne
Sin embargo, la primera línea no arroja ninguna excepción. De la documentación: "Se intentará resolver el nombre de host en una InetAddress. Si ese intento falla, la dirección se marcará como no resuelta"
ady
En cuyo caso se resolverá mediante el connect()método, pero no bajo el control de un tiempo de espera.
Marqués de Lorne
8

No puede controlar el tiempo de espera debido a UnknownHostException. Estos son tiempos de DNS. Solo puede controlar el tiempo de espera de conexión dado un host válido. Ninguna de las respuestas anteriores aborda este punto correctamente.

Pero me cuesta creer que realmente obtenga una UnknownHostExceptioncuando especifique una dirección IP en lugar de un nombre de host.

EDITAR Para controlar los tiempos de espera de DNS de Java, vea esta respuesta .

Marqués de Lorne
fuente