Socket Syncronisierung & Alone

Bizarrus

Bekanntes Mitglied
Halli Hallo =)

Bin zurzeit ein kleinen Chat am Programmieren, alles super toll =)

Ich bin aber leider auf einem Problem gestoßen:

Da alle Daten via Syncronisize vom Server an alle Clients weitergeleitet werden, gibt es hierbei das Problem, das diverse Aktionen bei anderen Clients ausgeführt werden, die garnicht gewollt sind.

Beispiel das "Einloggen".
Der Client sendet zum Server den String "l\0Nickname\0Passwort\0Channel".
Der Server überprüft nun in der Datenbank ob der angegebene Benutzername existiert, und sendet dann zum Clienten "l\0true" bzw "l\0false".

Und hierbei entsteht das Problem:
Da der Server l\0true an alle Clients sendet, führen diese alle weitere aktionen durch.

Meine Lösung wäre nun, den Server etwas umzuorganisieren, das solche aktivitäten nicht via Syncronisize durchgeführt werden.

Jezt habe ich aber leider keine Wirkliche Idee, wie ich dies löse.
Die Clients werden in einer Hashtable gestored, der Server sendet dann durch folgende Methode die Nachrichten zu allen Clients:

Java:
private Hashtable client_table = new Hashtable();

[...]

Enumeration getOutputStreams() {
	return client_table.elements();
}

void sendToAll(String message) {
	synchronized(client_table) {
		for(Enumeration e = getOutputStreams(); e.hasMoreElements();) {
			DataOutputStream connection_output = (DataOutputStream)e.nextElement();
			try {
				connection_output.writeUTF(message);
			} catch(IOException ie) {
				/* Do Nothing */
			}
		}
	}
}

Wie schreibe ich nun eine weitere Methode, ohne Syncronisation, der aber eine Nachricht nur an einem bestimmten Client gesendet wird?

Ein Client wird folgendermaßen in der Hashtable gestored:
Java:
Socket client = server.accept();
System.out.println("c\\0new");
DataOutputStream dout = new DataOutputStream(client.getOutputStream());
client_table.put(client, dout);

Ich danke euch, für Hilfreiche Tipps und Tricks.

Mfg
Bizzi
 

Empire Phoenix

Top Contributor
erm ? das synchronize hat aber nichts damit zu tun das das an alle geschickt wird und die deshalb mist bauen..
schick die daten halt nur an denjenigen der sie erhalten soll.

Werde das gefühl nciht los das du irgetwelche snippets aussem Inet / voom freund zusammenkopiert hast und jetzt experimentelles Programmieren betreibst. Kurz lern/versteh was die zeilen bedeuten, dann nochmal.

ansonsten würde ich ja Generics verwenden um nicht casten zu müssen.
 
B

Bizzi

Gast
Its not irgendwelche Snippets aus dem Internet,..
Ich habe nur einzelne Snippets bzw Methoden hier aufgelistet, auf denen Sich dies bezieht (Wie du siehst...).

Was soll denn bitteschön sonst syncronized sein?

syncronized dient dazu, das (da der Server Multithreading ist) alle aktiven Threads synkron mit Daten bedient werden.
Heist soviel wie: Client (Thread1) sendet zum server "hi", Server sendet "hi" an alle anderen Clients (Thread1, Thread2, Thread3) "hi" zurück...

Wie soll ich denn die Daten an demjenigen senden, der die Erhalten soll?
Das war doch meine Frage.

Die Clients werden in einer Hashtable gestored, und wie spreche ich nun einen Clienten explizit an, ohne die Methode SendToAll (siehe oben) verwenden zu müssen?
 

Michael...

Top Contributor
Was soll denn bitteschön sonst syncronized sein?

syncronized dient dazu, das (da der Server Multithreading ist) alle aktiven Threads synkron mit Daten bedient werden.
Von welchen Threads redest Du hier? Meinst Du mit Threads die Clients? Die wirst Du niemals "synchron" mit Daten versorgen können, da der Server die Clients sequentiell bedient und es sowieso ausserhalb Deiner Kontrolle ist, wann die gesendeten Daten tatsächlich beim Client ankommen.

Mit dem synchronized(client_table) hier wird sicher gestellt, dass nur ein Thread auf die Hashtable zugreifen kann, damit alle Threads (wieviele da auch immer auf Deinem Server laufen mögen) auf einem synchronizierten Datenstand arbeiten. So verhinderst Du hier z.B. dass während des Senden an die Clients, kein weiter Client in die Hashtable aufgenommen werden kann.
Vermutlich kannst Du das hier auch weg lassen, da es sowieso nicht das macht was Du denkst ;-) Einfach mal was zum Thema Threads/MultiThreading nachlassen (z.B. JavaInsel GalileoComputing)
Die Clients werden in einer Hashtable gestored, und wie spreche ich nun einen Clienten explizit an, ohne die Methode SendToAll (siehe oben) verwenden zu müssen?
Du musst nach dem Erhalt der Clientanfrage prüfen, um welche Art der Anfrage es sich handelt. Wenn die Anfrage an die anderen Clients verteilt werden soll --> sendToAll()
Handelt es sich um eine Authentifizierung, musst Du halt dahin antworten woher die Anfrage kam.
So wie ich das verstanden habe sendet der Client seinen Nickname mit der Anfrage mit, d.h. Du musst nur noch heraus finden, welcher OutputStream zu dem Nickname gehört und über diesen Stream die Antwort rausschicken.
Wobei ich für die Client Server Kommunikation ein anderes Protokoll überlegen/verwenden würde. Aber für den Anfang und zum Rumspielen sollte es das auch tun.
 

Empire Phoenix

Top Contributor
Ich würde die Clients ja ancha bsender ip/port unterscheiden lassen, dann kann man jedes packet(bzw stream bei tcp) zuordnen zu einem Client, oder falls keiner existiert es auf authentifizierung überprüfen.
 
B

Bizzi

Gast
Du musst nach dem Erhalt der Clientanfrage prüfen, um welche Art der Anfrage es sich handelt. Wenn die Anfrage an die anderen Clients verteilt werden soll --> sendToAll()
Handelt es sich um eine Authentifizierung, musst Du halt dahin antworten woher die Anfrage kam.
So wie ich das verstanden habe sendet der Client seinen Nickname mit der Anfrage mit, d.h. Du musst nur noch heraus finden, welcher OutputStream zu dem Nickname gehört und über diesen Stream die Antwort rausschicken.
So Logisch kann ich auch schon denken, wie es ablaufen könnte =)

Dafür könnte ich ja Theoretisch
Java:
DataOutputStream dout = new DataOutputStream(client.getOutputStream());
// dout.write() / dout.writeUTF() what else immer
Benutzen. Hierbei müsste ich nurnoch die Socketvariable "client" übergeben.

Java:
Ich würde die Clients ja ancha bsender ip/port unterscheiden lassen, dann kann man jedes packet(bzw stream bei tcp) zuordnen zu einem Client, oder falls keiner existiert es auf authentifizierung überprüfen.
Einerseits Gute Idee..

Ich bin gerade am überlegen:
Wenn mehrere User auf einer IP den Chat benutzen.

Aber das verschwindet mal ganz schnell wieder aus meinem Kopf, wenn ich "Port" sehe =)
Jeder Client benuzt dann ja nen freien Port..
 

Empire Phoenix

Top Contributor
speziell ip und port bietet sich bei udp an, bei tcp haste die ja schon durch die streams/thread unterscheiden. Bei udp haste ja nur ein enzigen socket und das wars
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
X axis stand alone-Server läuft nicht Netzwerkprogrammierung 2

Ähnliche Java Themen


Oben