2014-07-07 14 views
8

Programuję gniazdo. Wziąłem odniesienia z poniższego linku:Gniazdo EADDRINUSE (adres już w użyciu)

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

Poniżej szczegółów na temat mojego problemu. Utworzyłem bibliotekę Android dla tego ServerThread (moje wymaganie dotyczące projektu) i jest ona używana w aplikacji testowej.

Teraz aplikacja testowa łączy się z tym poprzez bibliotekę i wykonuje proces. Pierwszy raz to działa perfekcyjnie, ale jeśli zamknięte i ponownie rozbił z wyjątkiem:

próbował także serverSocket.setReuseAddress(true) to, ale bez powodzenia „EADDRINUSE (już w użyciu Adres)”.

Mój kod:

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()); 
     } 
    } 
} 

Jeśli zadzwonię serverSocket.close() otrzymuję wyjątek 2 jako gniazdo serwer końca. Wątek komunikacji jest taki sam jak podany w poprzednim linku.

+0

sam problem jak tutaj ... http://stackoverflow.com/questions/20068710/java-net-bindexception-bind-failed-eaddrinuse-address-already-in-use – morya

+0

Jaki typ gniazda są używasz? –

+0

Jak korzystać z gniazda? Czy możesz utworzyć przykład [Minimal, Complete i Verifyable] (http://stackoverflow.com/help/mcve) i pokazać nam? –

Odpowiedz

17

Trzeba zadzwonić setReuseAddress(true) zanim gniazdo jest zobowiązany do portu. Wywołujesz go po, ponieważ przekazujesz port do konstruktora, który natychmiast zwiąże gniazdo.

Spróbuj to zamiast:

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

Próbowałem tak dobrze, ale dostaję poniżej wyjątku ServerSocketThread wyjątek 2 = Gniazdo jest zamknięte – morya

+0

Na którym wierszu kodu dokładnie? Proszę być bardziej konkretnym. –

+0

Podczas wykonywania tej linii socket = serverSocket.accept(); wewnątrz pętli. – morya

7

Gniazda TCP (i prawdopodobnie niektóre inne) nie mogą ponownie używać tego samego portu przez okres po zamknięciu. Ma to zapobiec nieporozumieniom, jeśli dane w sieci pochodzą z istniejącego połączenia. Można zmienić to zachowanie, ale domyślnie należy poczekać na pewien okres czasu przed zezwoleniem na ponowne użycie portu.

Wywołanie tej poprawki to setReuseAddress(true) na gnieździe serwera. Ale nie jestem pewien, czy trzeba go wywołać na pierwszym lub drugim gnieździe, czy na obu.

Edit:

Oto blogu opisujący gniazda TCP TIME_WAIT państwa i dlatego istnieje: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html

2

Podczas gdy inne odpowiedzi podkreślił znaczenie setReuseAddress(true) inny problem, który może pojawić się skonstruować ServerSocket dwa razy i zadzwonić wiążą się z tymi samymi parametrami. Na przykład, jeśli wywołasz dwa razy kod run() pytania, serverSocket zostanie przypisane do nowej instancji klasy ServerSocket, ale stara nadal żyje, dopóki nie zostaną zebrane śmieci. Teraz budowanie z wartością portu jako parametrem jest równoznaczne z powiązaniem obiektu ServerSocket, a skończysz z dwoma ServerSocket związanymi z tym samym adresem, który jest zabroniony stąd wyjątek. Więc zbuduj serwerset z wybranym portem tylko raz!

0

Spróbuj utworzyć instancję SocketServer poza metodą 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(); 
     } 
} 
Powiązane problemy