# Überprüfen, ob der Client accepted wurde



## Reilif (9. Nov 2011)

Ich baue gerade eine Server/ Clientanwendung mit limitierten Multiclient. Sprich ich lasse genau 6 Verbindungen zu. Disconnected ein Client wird sein Platz wieder frei und ein neuer kann sich verbinden.

Soweit funktoniert das auch ganz gut, aber sind 6 Clients verbunden bekomme ich beim 7. Client keine Rückmeldung, dass das connecten mit dem Server nicht geklappt hat. Das ist aber leider notwendig, weil sich anschließend ein Frame öffnet das Informationen über den Server braucht. Das Fenster öffnet sich momentan zwar aber zeigt nichts an(da der Server den Client ja nicht accepted hat).

Vielen Dank für eure Mühe


----------



## bERt0r (9. Nov 2011)

Wenn dein Server die Verbindung nicht akzeptiert müsste im Client doch eine Exception fliegen...


----------



## Gast2 (10. Nov 2011)

bERt0r hat gesagt.:


> Wenn dein Server die Verbindung nicht akzeptiert müsste im Client doch eine Exception fliegen...


der Server akzeptiert ja die Verbindung - ist ja seine Aufgabe ... nach dem verbindungsaufbau muss der Server aber prüfen ob es mehr als 6 Clients sind und dann ggf. die Verbindung wieder trennen ... dazu soltle der Server den Client informieren wieso er wieder trennt

hand, mogel


----------



## Andi_CH (10. Nov 2011)

Glaskugel: Steht da irgendwo try - catch?

Ohne Code sind wir irgendwie aufgeschmissen.


----------



## Reilif (10. Nov 2011)

Code kommt:

Hier der Server:

```
/**
	 * Erstellt einen MultiClient Server mit limitierter Anzahl an Verbindungen.
	 * Accepted neue Clients nur solange Plätze auch wirklich frei sind.
	 * @param port
	 */
	public Server(int port) {
		try {
			server = new ServerSocket(port);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		connectedClients = new ConnectedClient[MAX_PLAYER];
		new Thread(new Runnable() {

			@Override
			public void run() {
				while(true){					
					while (connectionAllowed&&!allSlotsFull()) {
						ConnectedClient connectedClient;
						try {
							int nextid = getNextFreePlace();
							connectedClient = new ConnectedClient(Server.this,
									server.accept(), nextid);
							connectedClients[nextid] = connectedClient;
							System.out.println("New Client connected. IP: "
									+ connectedClient.getIP());
						} catch (IOException e) {
							e.printStackTrace();
						}
						
					}
				}
			}
		}).start();

	}
```

Hier der Konstruktor der Klasse ConnectedClient, die die Verwaltung der Verbindungen zu einem verbundenen Client aufrecht erhällt:


```
public ConnectedClient(Server server, Socket client, int nextId) {
		this.server = server;
		this.client = client;
		this.id = nextId;

		try {
			bufferedReader = new BufferedReader(new InputStreamReader(
					client.getInputStream()));
			writer = new PrintWriter(client.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
		isConnected = true;
		new Thread(this).start();
	}
```

Und hier am Ende das Client Gegenstück:


```
public Client(final NetzwerkController controller, String inetadress,
			int port, String name) {
		this.controller = controller;

		verbindeServer(inetadress, port);

		try {
			bufferedReader = new BufferedReader(new InputStreamReader(
					server.getInputStream()));
			bufferedWriter = new PrintWriter(server.getOutputStream());
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					try {
						String input = bufferedReader.readLine();
						controller.verarbeiteString(input);
					} catch (IOException e) {
						System.out.println("Geht nicht");
					}
				}
			}
		}).start();

	}

	private void verbindeServer(String inetadress, int port) {
		try {
			server = new Socket(inetadress, port);
		} catch (UnknownHostException e1) {
			System.out.println(e1);
		} catch (IOException e1) {
			System.out.println("Geht nicht");
		}

	}
```

Bei mehr Verbindungen als erlaubt betritt der Server nicht mehr den Teil in dem er Clients accepted. Dadurch wird ein dritter Client (bei 2 erlaubten Verbindungen) nicht mehr accepted. Der Socket auf der Clientseite registriert das anscheinend aber nicht, denn er wirft keine Exception


----------



## SlaterB (10. Nov 2011)

was genau passiert denn auf Client-Seite, wird blockierend gewartet?
setze vielleicht einen Timeout, wenn nach 5 sec nix passiert dann ist der Server eben kaputt


----------



## Reilif (10. Nov 2011)

Die frage ist dann aber, was ist "nix passiert". Ich hab die Methoden der Socket Klasse ausprobiert also: isConnected(); bekomme ich immer true;
getKeepAlive; bekomme ich immer false(auch bei Verbundene Clients)


Um deine Frage zubeantworten:

Sowohl der ConnectedClient auf Server Seite, als auch der Client beim Client horchen in einer endlos Schleife auf Nachrichten des Servers. Jeder String der reinkommt wird "zerlegt" und dann behandelt.


----------



## SlaterB (10. Nov 2011)

auf Serverseite wird doch gar nicht accept() ausgeführt, also gibt es gar keinen ConnectedClient auf Serverseite zu diesen zusätzlichen, nicht eingerichteten Verbindungen?!

du hast dort übrigens eine schlechte Umsetzung, wenn die innere Schleife mit dem accept() nicht arbeitet,
läuft da quasi eine while(true)-Schleife endlos, 100% Belastung für einen Rechenkern, 
setze ans Ende der äußeren Schleife ein Thread.sleep(500) und de reduzierst die Abermilliarden Durchläufe pro Sekunde auf 2,
oder Thread.sleep(50), hilft genauso und verringert die Tot-Zeit

> beim Client horchen in einer endlos Schleife auf Nachrichten des Servers
beim Client funktioniert der Verbindungsaufbau?
na auch egal, genauso kann dort die Regel eingebaut werden dass innerhalb einer bestimmten Zeit irgendeine Begrüßungskommunikation stattfinden muss,
wenn nicht gilt das quasi genauso als Timeout, wie auch immer umgesetzt, 
ist ein Thread in Endlos-Schleife-Lesen blockiert oder sonstwie beschäftigt ist, ob mit oder ohne Timeout, 
könnte ein zweiter Thread dazu das überwachen, wenn der den Socket schließt dürfte der erste Thread auch 'befreit' werden


----------



## Reilif (10. Nov 2011)

Das mit dem Sleep war das eig. drin. Muss bei einer meiner "Suche-den-Fehler" Aktionen wohl unglücklicherweise vernichtet worden sein.

Die Idee mit dem handshake hatte ich auch schon. Dachte bloß das es da vielleicht eine andere Methode gibt.

Danke für deine schnellen Antworten.

ps: Hätte jemand für soetwas schnelle einmal Code zur Hand?


----------



## Michael... (10. Nov 2011)

Reilif hat gesagt.:


> Das mit dem Sleep war das eig. drin.


Das mit dem sleep ist bei einer passenden Implementierung überflüssig.


Reilif hat gesagt.:


> ps: Hätte jemand für soetwas schnelle einmal Code zur Hand?


Wie der Zufall so will:
http://www.java-forum.org/netzwerkprogrammierung/96318-server-programm-read-beendet.html#post612490
Bei dem Beispiel lässt der Server nur eine Verbindung gleichzeitig zu. Versucht sich ein zweiter Client am Server anzumelden, wird dieser vom Server anständig darüber informiert, dass "besetzt" ist und die Verbindung beendet.


----------



## Reilif (10. Nov 2011)

Hab es jetzt hinbekommen. Hab wirklich auf eine Art Handshake zurückgegriffen. Funktioniert jetzt einwandfrei


----------



## Domi F (11. Nov 2011)

Ein Handshake sollte nicht notwendig sein. Dein Problem ist, dass das OS TCP-Verbindungen automatisch entgegen nimmt. Es gibt dazu den BACKLOG-Wert, der steuert wieviele Verbindungen vom OS akzeptiert werden, ohne dass dein Code sie auch akzeptiert hat. An diesem Wert herum zu fummeln, bringt die aber kaum etwas, da die verschiedenen OS den von dir gesetzten Wert noch anpassen (typischerweise ist der >= 50). Für weitere Info kannst du nach dem BACKLOG googlen.

Der accept-Aufruf blockiert, bis jemand verbindet. Daher solltest du deine deine while(true)-Schlaufe anders aufbauen. Im Prinzip (in Pseudocode):

```
while(true)
{
   socket = serversocket.accept() //blockiert bis jemand verbindet
   if( Maximale Anzahl erreicht)
      socket.close
   else
      dein Verbindungs-Handling
}
```
So ist kein sleep notwendig und die Verbindung wird beim Client gleich wieder abgebaut, wenn das Limit erreicht ist.


----------

