Socket Mehrere gleichzeitig eingehende Nachrichten

Creylon

Mitglied
Hallo,

ich saß die letzten Tage an einem Server für ein kleines Spiel. Synchro läuft super, bis ich es mit 3 Leuten gleichzeitig ausprobiert habe...

Ich bekomme eine java.io_OptionalDataException, was in meinen Augen heißt, das der aktuelle Client gleichzeitig die Nachricht von den beiden anderen Clients bekommt.

Hat jemand eine Ahnung, wie ich das am besten Löse?

Ich habe überlegt, ob man, wenn es mehrere Nachrichten sind, diese in einen Array schreiben könnte.

MIt freundlichen Grüßen
 

Creylon

Mitglied
Naja man kann nicht wirklich viel sehen.

Hier sendet der Server
Java:
message = (Message)thisClient.ois.readObject();
				
				message.ID = thisClient.ID;
				
				for(Clients client : clients)
				{
					if(client.ID != thisClient.ID)
					{
						client.oos.writeObject(message);
						client.oos.flush();
					}
				}

Hier empfängt der Client.

Java:
public void run() {
		while(true)
		{
			try {
				
				message = (Message)ois.readObject();
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			HasInput = true;
			
		}
	}

Ich habe für jeden Client auf dem Server einen Thread, weswegen mehrere Nachrichten gleichzeitig kommen.
 
T

tuxedo

Gast
JabvaDoc lesen könnte helfen:

OptionalDataException (Java 2 Platform SE v1.4.2)

This exception may be thrown in two cases:

* An attempt was made to read an object when the next element in the stream is primitive data. In this case, the OptionalDataException's length field is set to the number of bytes of primitive data immediately readable from the stream, and the eof field is set to false.
* An attempt was made to read past the end of data consumable by a class-defined readObject or readExternal method. In this case, the OptionalDataException's eof field is set to true, and the length field is set to 0.

Scheint so als ob du dein eigenes Protokoll nicht sauber einhälst.

Schreibst du vielleicht mit mehreren Threads in ein und denselben Stream eines einzelnen Clients? Stelle sicher dass nur immer ein Thread in einen OutputStream was schreiben kann. Evtl so:

Java:
ObjectOutputStream oos = client.oos;
synchronized(oos) {
   oos.writeObject(message);
   oos.flush();
}

Nebenbei: statischer Zugriff auf solche Variablen mag zwar an manchen Stellen praktisch sein, wird aber generell nicht empfohlen. Besser ein "getOos()" in "client" einbauen.

- Alex
 

Creylon

Mitglied
Die Methode funktioniert, jedoch lagt dann bei drei Spielern immer einer, weil ja immer nur von einer Seite was kommt.

Ich habe mir nun auf meinem Server einen Array entsprechend der Slotanzahl angelegt. Ich empfange vom client eine Message, trag sie in den für ihn vorgesehen ArrayIndex hinein und schick den gesamt Array an den einen Client zurück.

Mein Problem: Beim Client kommt zwar einmal die Nachricht an, die Koordinaten beispielsweise sind dann immer 0...
 
T

tuxedo

Gast
Die Methode funktioniert, jedoch lagt dann bei drei Spielern immer einer, weil ja immer nur von einer Seite was kommt.

Ist IMO auch etwas blödsinnig das ganze Spiel über alle Clients zu synchronisieren. Wenn du ein Client hast der eine Nachricht synchron zum Server schickt, und dieser synchron sequentiell alle Clients benachrichtigt, dann skaliert das gaaanz schlecht. Je mehr Clients zu hast, desto langsamer wird es.

Optimieren könntest du jetzt in der Schleife in der alle Clients benachrichtigt werden. An der Stelle kannst du parallelisieren. Warum einen nach dem anderen informieren? Spendiere 2-3 Threads die sich gleichzeitig um diese Aufgabe kümmern.

Vielleicht solltest du deine Spiellogik auch nochmal überdenken: Ist es wirklich notwendig dass der Client wartet bis alle anderen Clients seine Meldung erhalten haben?

Ich habe mir nun auf meinem Server einen Array entsprechend der Slotanzahl angelegt. Ich empfange vom client eine Message, trag sie in den für ihn vorgesehen ArrayIndex hinein und schick den gesamt Array an den einen Client zurück.

Mein Problem: Beim Client kommt zwar einmal die Nachricht an, die Koordinaten beispielsweise sind dann immer 0...

Keine Ahnung was du hier treibst. Klingt auf alle Fälle "seltsam".

Generell mein Rat:

* Synchrone Stellen in der High-Level Kommunikation verhinden wo's nur geht. Sprich: Einen Client nicht auf eine Antwort des Servers warten lassen wenns nicht doch anders geht. Heisst nicht, dass du im Code nirgends ein "synchronized" Block verwenden darfst. Oft kommst du um sowas gar nicht drum rum.

Gruß
Alex
 

Creylon

Mitglied
Okay anscheinend hast du das nicht so ganze verstanden ^^

Ich will erstmal nur erreichen, dass man zusammen auf einem Server ist, wo man einfach nur seine Spielfigur bewegen kann und die Positionen der anderen Spielern immer aktualisiert werden.

1. Meine Position an den Server schicken
2. Positionen der anderen Spieler empfangen
3. Spieler an der entsprechenden Stelle Zeichnen

zu 1.

Ich hab ein Objekt, dass alle nötigen Informationen zu meinem Spieler enthält. (X und Y)

Dieses sende ich via ObjectOutputStream zum Server.

zu 2.

Ich erhalte einen Array des selben Objektes, welches ich schon zum Server hingeschickt habe, wobei jeder verbundene Spieler einen Index hat.

zu 3.

Ich lese das ganze mit einer For-Schleife aus und aktualisiere die Koordinaten oder erstelle falls notwendig einen neuen Spieler.


Server:
Hier habe ich einen Array, der stehts alle Koordinaten verbundener Spieler enthält.

Jeder Client hat einen eigenen Thread. Ich empfange also die Koordinaten des einen Spielers und aktualisiere damit die aus dem Array.

Nun nehme ich diesen Array, der, wie bereits erwähnt, die Koordinaten aller Spieler enthält, und sende diesen an den einen Client zurück, von dem ich vorher die Koordinaten bekommen habe.

Dies geschieht separat für jeden einzelnen Client parallel.


Ich hoffe ich konnte es etwas verständlicher erklären.
 
T

tuxedo

Gast
Okay, verstanden. D.h. ein Client bekommt nur dann die Positionsupdates anderer Spieler mit, wenn er selbst ein Update sendet? Würde das von "pull" auf "push" umbauen. Positions-Updates werden empfangen wenn es der Server für richtig hält die Clients mit neuen Updates zu versehen. Aber gut, musst du wissen was für dich geschickter ist.

Bzgl. dem "ist 0"... Ich glaube da bist du in eine Object*Stream-Falle getappt.... Der OOS und der OIS merken sich, welche Objekte sie bereits übertragen haben. Wird das selbe Objekt nochmal übertragen (nur mit anderen Werten drin), dann wird nicht das Objekt neu serialisiert, sondern nur eine Referenz-ID übertragen. Der Empfänger weiß dann: "Oh, eine Referenz-ID "XYZ". Das ist das Objekt von vorhin. Prima. Das kenn ich schon." Und der Server spart sich das aufwendige serialisieren des Objekts. Geht schneller, klar, aber du hast nicht den gewünschten Effekt, nämlich das gleiche Objekt, nur mit geändertem Inhalt übertragen...

Das Problem ist hier nochmal ganz gut veranschaulicht: [JavaSpecialists 088] - Resetting ObjectOutputStream

Die Lösung:

Java:
oos.reset();

Macht aber nur dann Sinn zu resetten, wenn das Objekt tatsächlich neuen Inhalt hat. Wenn du immer resettest, sparst du dir das prüfen ob sich der Objektinhalt geändert hat, aber du verlierst den Vorteil dass nur eine ID und nicht das ganze Objekt übertragen werden muss.

- Alex
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
7 Mehrere Verbindungen gleichzeitig in einem Thread mit ApacheHTTP Netzwerkprogrammierung 7
A Jakarta Commons HTTPClient: Mehrere Requests gleichzeitig Netzwerkprogrammierung 2
M Mehrere Ports gleichzeitig abhören Netzwerkprogrammierung 5
izoards Mehrere TCP Verbindungen auf einen Server [alles Local] Netzwerkprogrammierung 2
Aruetiise Socket Mehrere Clients Netzwerkprogrammierung 4
E Mehrere Sockets Netzwerkprogrammierung 2
C Mehrere Spielewelten im Multiplayer Netzwerkprogrammierung 2
J Framework mehrere Clients/ Server-Broadcast/oracle XE/ XML Netzwerkprogrammierung 1
V Server / mehrere Clients / MySQL / Konzept Netzwerkprogrammierung 2
S Server - Mehrere Klassen sollen Daten senden und empfangen Netzwerkprogrammierung 25
N SOCKET mehrere Requests, keep Alive serverspezifisch? Netzwerkprogrammierung 3
Z Socket [Chatprogramm] Mehrere Clients an einen Server Netzwerkprogrammierung 10
V Authentifikation über mehrere Server? Netzwerkprogrammierung 3
G Socket Mehrere Clientanmeldungen am Server Netzwerkprogrammierung 13
D Mehrere Clients über Java-Sockets Netzwerkprogrammierung 13
cedi Socket Mehrere Clients an einem Server Netzwerkprogrammierung 4
B SSH mit Jsch, mehrere Befehle senden Netzwerkprogrammierung 4
F Socket Verbindungen über mehrere Server Netzwerkprogrammierung 4
M Jetty Konfiguration mehrere Handler? Netzwerkprogrammierung 2
F UDP Server - mehrere Pakete auf einmal Netzwerkprogrammierung 12
A Mehrere gleich Packete behandeln Netzwerkprogrammierung 4
L Socket Chat Server für mehrere Clients Netzwerkprogrammierung 7
R mehrere MySQL-Zugriffe Netzwerkprogrammierung 3
B Paralleler Dateitransfer: Ein Client - Mehrere Sockets? Wie connecten? Netzwerkprogrammierung 16
S Mehrere Attachments mit JavaMail API auslesen Netzwerkprogrammierung 3
O Mehrere Datei per DataInput/OutputStream über Socket Netzwerkprogrammierung 12
A Datenverteilung: Mehrere Threads verwenden? Netzwerkprogrammierung 4
T Netzwerkchat Problem: Mehrere Nachrichten ~ Anfängerproblem Netzwerkprogrammierung 3
W Bestimmt IP Adresse verwenden wenn man mehrere hat Netzwerkprogrammierung 5
D Clients sollen mehrere Sessions starten Netzwerkprogrammierung 11
R Mehrere Dateien über einen Socket senden Netzwerkprogrammierung 2
G Nachricht an mehrere Clients schicken Netzwerkprogrammierung 10
L mehrere Streams über einen Socket? Netzwerkprogrammierung 8
V Mehrere Streams durch einen Stream senden Netzwerkprogrammierung 14
E Mehrere / bestimmte Netzwerkkarten ansteuern Netzwerkprogrammierung 10
F Mehrere Attachments mit JavaMail API Netzwerkprogrammierung 2
G Proxy und mehrere Verbindungen Netzwerkprogrammierung 4
G Mehrere SSL Verbindungen Netzwerkprogrammierung 2
A Mit Client auf mehrere Server zugreifen Netzwerkprogrammierung 5
TRunKX Ein Port mehrere Verbindungen? Netzwerkprogrammierung 7
G Server an mehrere Clients Netzwerkprogrammierung 15
L JavaMail: Automatisches Email Versand (mehrere Empfänger) Netzwerkprogrammierung 4
U Einen HandlerThread, der mehrere Verbindungen verwaltet? Netzwerkprogrammierung 2
X mehrere Request über eine HttpURLConnection Netzwerkprogrammierung 2
S eclipse: client/server gleichzeitig starten Netzwerkprogrammierung 8
A RMI: Wieviele Clients können sich gleichzeitig anmelden? Netzwerkprogrammierung 34
K Windows 10 Threads gleichzeitig Netzwerkprogrammierung 18
F nur ein benutzer gleichzeitig / locking mechanismus Netzwerkprogrammierung 3
A Rmi Client und Server Gleichzeitig! Netzwerkprogrammierung 3
N Java NIO eingehende und ausgehende Verbindungen mit einem Selector Netzwerkprogrammierung 12
O eingehende Daten speichern Netzwerkprogrammierung 3

Ähnliche Java Themen

Neue Themen


Oben