2014-07-07 25 views
8

Sto facendo programmazione socket. Presi di riferimento da sotto il collegamento:Socket EADDRINUSE (Indirizzo già in uso)

http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/

Di seguito è riportato dettaglio circa il mio problema. Ho creato Android per questo ServerThread (il mio requisito di progetto), e questo è usato nell'app di test.

Ora l'app di test si collega a questo tramite lib e fa il processo. La prima volta funziona perfettamente bene, ma se ho chiuso e riaprirlo è schiantato con l'eccezione:

"EADDRINUSE (Indirizzo già in uso)"

anche provato serverSocket.setReuseAddress(true) questo, ma senza fortuna.

Il mio codice:

public void run() { 
    Socket socket = null; 
    try { 
     serverSocket = new ServerSocket(SERVER_PORT); 
     serverSocket.setReuseAddress(true); 

    } catch (IOException e) { 
     Log.e(TAG, "exception1= " + e.getMessage()); 
    } 
    while (!Thread.currentThread().isInterrupted()) { 
     try { 

      socket = serverSocket.accept(); 
      Log.d(TAG, "server Connected.......!!!!"); 

      communicationThread = new CommunicationThread(
        socket); 
      commThread = new Thread(communicationThread); 
      commThread.start(); 

     } catch (IOException e) { 
      Log.e(TAG, "exception 2=" + e.getMessage()); 
     } 
    } 
} 

Se chiamo serverSocket.close() io sono sempre un'eccezione 2 come socket server vicino. Il thread di comunicazione è lo stesso del collegamento precedente.

+0

stesso problema qui ... http://stackoverflow.com/questions/20068710/java-net-bindexception-bind-failed-eaddrinuse-address-already-in-use – morya

+0

Che tipo di presa sono stai usando? –

+0

Come si usa la presa? Puoi creare un esempio [Minimo, Completo e Verificabile] (http://stackoverflow.com/help/mcve) e mostrarci? –

risposta

17

si deve chiamare setReuseAddress(true) prima che il socket è associato alla porta. Lo stai chiamando dopo, perché stai passando la porta al costruttore, che legherà immediatamente il socket.

Prova a modificare:

serverSocket = new ServerSocket(); // <-- create an unbound socket first 
serverSocket.setReuseAddress(true); 
serverSocket.bind(new InetSocketAddress(SERVER_PORT)); // <-- now bind it 
+0

L'ho provato bene ma sto ottenendo sotto l'eccezione eccezione ServerSocketThread 2 = La presa è chiusa – morya

+0

Su quale riga di codice esattamente? Si prega di essere più specifici. –

+0

Durante l'esecuzione di questa linea socket = serverSocket.accept(); dentro mentre ciclo. – morya

7

I socket TCP (e probabilmente alcuni altri) non possono riutilizzare la stessa porta per un periodo dopo la chiusura. Questo per evitare confusione se ci sono dati sulla rete da una connessione esistente. È possibile ignorare questo comportamento, ma l'impostazione predefinita è di attendere un certo periodo di tempo prima di consentire il riutilizzo della porta.

La chiamata per risolvere il problema è setReuseAddress(true) sul socket del server. Ma non sono sicuro se debba essere chiamato sul primo socket o sul secondo, o entrambi.

Edit:

Ecco un post che descrive il socket TCP TIME_WAIT stato e perché esiste: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html

2

Mentre le altre risposte hanno sottolineato l'importanza di setReuseAddress(true), un altro problema che potrebbe sorgere è quello di costruire il ServerSocket due volte e chiamare legano con gli stessi parametri. Ad esempio se si chiama due volte il codice run() della domanda, serverSocket verrà assegnato a una nuova istanza della classe ServerSocket, ma quella precedente è ancora in vita fino a quando non viene raccolta la garbage collection. Ora la costruzione del valore di porta come parametro equivale a legare l'oggetto ServerSocket e si andrà a finire con due ServerSocket associati allo stesso indirizzo, il che è vietato da ciò l'eccezione. Quindi crea il tuo server socket con la porta scelta solo una volta!

0

Provare a creare l'istanza di SocketServer al di fuori del metodo run().

protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState) 
    try { 
     // create a new instance of an unbound socket first 
     serverSocket = new ServerSocket(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
} 
Problemi correlati