2011-03-22 21 views
6

Tengo una GUI con una lista de servidores para conectarme. Si un usuario hace clic en un servidor, se conecta a él. Si un usuario hace clic en un segundo servidor, desconectará el primero y se conectará al segundo. Cada nueva conexión se ejecuta en un nuevo hilo para que el programa pueda realizar otras tareas.Interrumpir un socket de conexión

Sin embargo, si un usuario hace clic en un segundo servidor mientras el primero todavía se está conectando, hay dos conexiones simultáneas.

Estoy conectando el uso de este, y conectar() es la línea que bloquea:

Socket socket = new Socket(); 
socket.connect(socketAddress, connectTimeout); 

pensé que tal vez Thread.currentThread().interrupt(); quiere trabajar, pero no lo hicieron.

¿Tengo que reestructurar un poco mi código para que continúe haciendo la primera conexión, pero la cierre inmediatamente después? ¿O hay realmente una forma de interrumpir el método de conexión?

Respuesta

2

Si está utilizando una implementación de socket de bloqueo, interrumpir el hilo no se 'cancelará' ni interrumpirá su conexión de socket. La única forma de salir de la "llamada de bloqueo" es "cerrar" el socket. Puede exponer un método en sus tareas ejecutables (por ejemplo, cancel) que cierra el socket y limpia los recursos cuando el usuario intenta conectarse a un segundo servidor.

Si lo desea, puede tener un look at my throwaway attempt al interrumpir los hilos que hacen llamadas de bloqueo.

+0

Cuando intento Socket.close(), se dice que toma es nula .. pero debe ser una válida (pero no conectado) Objeto de socket Estoy llamando a close() en la misma clase Runnable dentro de un método llamado disconnect(), que es llamado por otro hilo, ¿es por esto? ¿Tiene que invocarse close() en el socket directamente desde un hilo diferente? – Matt

+0

@Matt: Sería difícil de decir sin echarle un vistazo al código, pero solo quería confirmarlo; es la variable de socket y la variable de instancia o un método con un alcance uno? ¿Estás seguro de que el atributo 'socket' de la tarea Runnable no es nulo? En caso afirmativo, ¿puedes tratar de hacer que la variable del socket sea 'volátil' en el objeto de la tarea e intentarlo de nuevo? ¿Todavía falla? –

1

¿Se puede utilizar un zócalo que no sea de bloqueo? No soy muy experto en Java, pero parece que SocketChannel es su clase de socket sin bloqueo.

Aquí se muestra un ejemplo:

// Create a non-blocking socket and check for connections 
try { 
    // Create a non-blocking socket channel on port 80 
    SocketChannel sChannel = createSocketChannel("hostname.com", 80); 

    // Before the socket is usable, the connection must be completed 
    // by calling finishConnect(), which is non-blocking 
    while (!sChannel.finishConnect()) { 
     // Do something else 
    } 
    // Socket channel is now ready to use 
} catch (IOException e) { 
} 

Tomado de aquí: http://www.exampledepot.com/egs/java.nio/NbClientSocket.html

Dentro del bucle while puede comprobar si hay alguna notificación compartida que debe ser cancelado y rescatar, cerrando la SocketChannel a medida que avanza.

1

Intenté las respuestas sugeridas pero nada funcionó para mí. Entonces, lo que hice fue, en lugar de configurar el tiempo de espera de conexión a 10 segundos, intento conectarme 5 veces seguidas con un tiempo de espera de conexión de 2 segundos. También tengo una variable global boolean cancelConnection declarada.

Cada vez que se lanza una excepción de tiempo de espera, puedo salir del bucle o continuar el ciclo en función del valor de cancelConnection.

He aquí un fragmento de código de una aplicación para Android que estoy escribiendo:

try { 
    SocketAddress socketaddres = new InetSocketAddress(server.ip,server.port); 
    int max=5; 
    for (int i = 1; i<=max; i++) { 
     try { 
      socket = new Socket(); 
      socket.connect(socketaddres, 2000); 
      break; 
     } catch (Exception e) { 
      Log.d(TAG, "attempt "+i+ " failed"); 
      if (cancelConnection) { 
       Log.d(TAG, "cancelling connection"); 
       throw new Exception(); 
      } else if (i==max) { 
       throw new Exception(); 
      } 
     } 
    } 
} catch (Exception e) { 
    if (cancelConnection) { 
      // Do whatever you would do after connection was canceled. 
    } else { 
      // Do whatever you would do after connection error or timeout 
    } 
} 
Cuestiones relacionadas