2010-09-13 28 views
24

Estoy usando un cliente de socket Java. En un caso en el que el servidor todavía está conectado a mi cliente pero no envía una respuesta a mi mensaje, finalmente obtengo una excepción de tiempo de espera de lectura.¿Cómo se puede conectar y cerrar un socket?

En ese caso, quiero probar para ver si debo volver a conectar mi socket o simplemente mantenerlo reutilizado.

utilizo esta condición:

if (!socket.isConnected() || socket.isClosed() || !socket.isBound()) { 
    try { 
     socket.close(); 
    } catch (IOException e1) { 
    } 
    // Wait on a new connection 
    socket = connectSocket(.....); 
} 

Pero siempre parece volver a conectar. Cuando intento acceder a los valores de las propiedades booleanas veo esto:

conexión: verdadera cerrado: cierto límite: verdadera

¿Cómo puede ser conectada y cerrada?

TIA

+0

Las llamadas a métodos no son atómicas ... ¿quizás otro hilo está cerrando el socket entre las llamadas 'isConnected()' y 'isClosed()'? Tal vez sincronizar en el objeto de socket primero? – Powerlord

+0

Eso es fácil de probar si solo invierte el orden de los controles para 'isConnected()' y 'isClosed()'. –

Respuesta

66

This thread tiene algunas discusiones útiles sobre este tema. Resulta que Socket.isConnected devuelve verdadero si se ha conectado (alguna vez) con éxito.

Desde el hilo anterior:

Cuando se utiliza Socket(), que usted parece haber pasado por alto, Socket.isConnected() le indica si se ha llamado Socket.connect() o no. Del mismo modo para isClosed() y close().

confusión sobre estos métodos resulta de confundir el estado de la toma de , que está bajo el control de la aplicación, con el estado de la conexión global, que está bajo el control del protocolo. isConnected() y isClosed() diga lo que ha hecho con el socket. No hay otras API que no sean de lectura y escritura para determinar el estado de de la conexión.

La documentación dice:

devuelve verdadero si la toma exitosamente conectado a un servidor

y no como uno quizás podría esperar "devuelve verdadero si el conector está conectado a un servidor ".

El comportamiento se puede confirmar observando la fuente de zócalo:

public boolean isConnected() { 
    // Before 1.3 Sockets were always connected during creation 
    return connected || oldImpl; 
} 

También puede ejecutar este pequeño fragmento de prueba:

Socket s = new Socket(); 

System.out.println("isConnected: " + s.isConnected() + 
        " isBound: "  + s.isBound() + 
        " isClosed: " + s.isClosed()); 

s.connect(new InetSocketAddress("google.com", 80)); 

System.out.println("isConnected: " + s.isConnected() + 
        " isBound: " + s.isBound() + 
        " isClosed: " + s.isClosed()); 

s.close(); 

System.out.println("isConnected: " + s.isConnected() + 
        " isBound: " + s.isBound() + 
        " isClosed: " + s.isClosed()); 

que imprime:

isConnected: false isBound: false isClosed: false 
isConnected: true isBound: true isClosed: false 
isConnected: true isBound: true isClosed: true 

Debo decir que la documentación no está clara en este punto, y que el nombre-método es un poco m Esta liderando.

+11

+1 ¡Bravo! ¡Gran respuesta! –

+2

Gracias. Ahora está claro para mí. – sproketboy

+0

Enlace roto, pero de las citas parece haber sido levantado holus-bolus de las respuestas aquí o en los foros Sun/Oracle Java, muchos de ellos por mí. – EJP

Cuestiones relacionadas