# "Address already in use" accept() abbrechen?



## Guest (13. Feb 2009)

Hab hier einen Server und einen Client die sich jeweils beide beliebig beenden lassen (soll auch so sein).
Folgendes Problem:

Wenn vor beenden der Verbindung der Client mit dem Server verbunden war, dann funktioniert alles. 
Wenn ich aber vor Verbindungsaufbau den Server beende und dann versuche eine neue Verbindung aufzubauen, dann kommt bekomme ich folgendes:

java.net.BindException: Address already in use: JVM_Bind
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(Unknown Source)
at java.net.ServerSocket.bind(Unknown Source)
at java.net.ServerSocket.<init>(Unknown Source)
at java.net.ServerSocket.<init>(Unknown Source)

Hab schon etwas gesucht und gefunden, dass der man nur einen ServerSocket pro Port erstellen kann.
Hier ist ein älterer Bug bei dem der selbe Fehler auftritt: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4492308

Wenn ich einen Verbindungsversuch mit dem Server starte ohne vom Client aus eine Verbindung aufzubauen, dann haengt der ServerSocket an server.accept() und wartet. Wenn nun der Server beendet wird und ein neuer Verbindungsversuch gestartet wird, dann konnte natuerlich nach accept() nichts weiteres mehr ausgefueht werden und der Code laeuft erst wieder bis zu accept() ab. Ich kann kein close() nach accept() aufrufen, da das ja nur aufgerufen wird, wenn eine Verbindung aufgebaut wurde. Davon abgesehen waere es ja sinnlos direkt nach Verbindungsaufbau close() aufzurufen. Bei dem neuen Verbindungsversuch ist also der "alte" ServerSocket noch offen und blockiert den port.
Ich muesste glaube ich close() vor dem Erstellen des ServerSockets aufrufen (beim ersten mal koennte ich dann einfach die NullPointerException abfangen), das geht aber in meinem Fall nicht, da der Server in einer Klasse liegt von der bei jeder neuen Verbindung eine Instanz erzeugt wird und der ServerSocket eine Klassen"variable" ist.
Gibt es vielleicht eine Moeglichkeit von einer anderen Klasse aus accept() vorzeitig zu beenden bzw. zu ueberspringen und dann close() aufzurufen, ohne dass vorher eine Verbindung aufgebaut wurde?


----------



## musiKk (13. Feb 2009)

Anonymous hat gesagt.:
			
		

> Gibt es vielleicht eine Moeglichkeit von einer anderen Klasse aus accept() vorzeitig zu beenden bzw. zu ueberspringen und dann close() aufzurufen, ohne dass vorher eine Verbindung aufgebaut wurde?


Mit einem anderen Thread geht das. Beim accept() fliegt dann eine SockeException, auf die muss dann natürlich noch entsprechend reagiert werden.

Mangels Code verstehe ich das Problem allerdings nicht so ganz.


----------



## Guest (13. Feb 2009)

Hmm.. dachte der Code waere dazu eher weniger nuetzlich, aber ich poste ihn trotzdem mal (einfachhalber unwichtiges rausgenommen):


```
public class Net extends Thread {
	
	private ServerSocket server;
	private Socket client;
	private PrintWriter out;
	private BufferedReader in;
	
	private boolean isHost;
	public String hostip, sendThis="";
	public int port, status = 0;
	public static final int DISCONNECTED = 0, CONNECTING = 1, CONNECTED = 2;		
	
	public Net(boolean isHost, String hostip, int port) {
		this.isHost = isHost;
		this.hostip = hostip;
		this.port = port;
		status = CONNECTING;
		start();
	}	
	
	public void send(String sendThis) {
		this.sendThis = sendThis;
	}
	
	public void run() {
		String error ="";
		runnetwork:
			// sleep 10ms
			switch(status) {
			case CONNECTING:
				try {
					if(isHost) {
						server = new ServerSocket(port);
						client = server.accept();
					} else {
					client = new Socket(hostip, port);
					}	
					in = new BufferedReader(new InputStreamReader(client.getInputStream()));
					out = new PrintWriter(client.getOutputStream());
					status=CONNECTED;
				} catch (IOException e) {
					status=DISCONNECTED;
				}	
			break;	
			case CONNECTED:
				// Senden/Empfangen
				// Exception -->	status=DISCONNECTED;
			break;
			case DISCONNECTED:
				break runnetwork;
			}				
		}
		try {
			if(isHost){
				server.close();
			}
			client.close();
			in.close();
			out.close();
		} catch (Exception e) {}
	}

}
```

Das Problem liegt in Zeile 33,34. Eine andere Klasse instanziert ein Net Objekt wenn eine neue Verbindung aufgebaut werden soll.
Beispiel:
-Es wird ein Net Objekt instanziert mit: new Net(true, "", port);
-Bevor ein anderer Rechner sich als Client anmeldet (mit new Net(false, ip, port); )
 wird status=DISCONNECTED; gesetzt (was in diesem Fall nichts ausloest da bei server.accept() gewartet wird.)
- Ein neues Net(true, "", port); Objekt wird instanziert. ---> BindException

Was genau muss ich in einem anderen Thread machen um die SocketException auszuloesen?


----------



## musiKk (14. Feb 2009)

Eh... ein close(), wie du schon geschrieben hast.


----------



## Guest (14. Feb 2009)

Ahh.. ja natuerlich. Die Loesung war wohl zu simpel um drauf zu kommen <.<


----------

