# Multiplayer eines Spiels



## Kayuke (17. Jan 2013)

Guten Tag, ich habe nun mein erstes fertiges Spiel, ein 2D Helikopter Spiel, mit Waffen, Shop, Endgegner, Leveln etc.

Nun möchte ich dies im LAN zu zweit Spielen können, dazu habe ich mir bereits angeschaut wie ein Server und wie ein Client aufgebaut ist und eine erste Verbindung hergestellt. Unterm Menü Multiplayer kann nun ein Client "Create" klicken und der andere kann "Joinen". Nun stellen sich mir hier noch ein  paar Fragen wie ich es am besten angehe:

1. Der Server ist eine Endlosschleife da er immer wieder prüft ob was neues Empfangen wurde, muss ich hier mit Multithreading arbeiten damit ich nebenbei ein Spiel gleichzeitig laufen lassen kann oder bau ich den Server ins Spiel ein und pack quasi die Abfragen vom Server z.B. in ActionPerformed ein was auch ganze Zeit aufgerufen wird?

2. Theoretisch braucht der Server vom anderen Clienten nur eine Instanz des Spielobjekts, da dort die Bewegung, Schüsse, Punkte und alles andere gespeichert werden, der Client hingegen braucht die ArrayListen der gegner, powerups, coins, hindernisse etc. Kann ich das Problemlos übertragen? Ich habe gelesen das bei der einfachen Verbindung die ich gerade habe nur wenige bytes verfügbar sind.

3. Jegliche Tipps zu dem Thema, hab jetzt fast alle Links bei Google durch und ich wüsste auch wie ich jetzt anfangen "könnte" aber ob das der Beste weg ist weiß ich nicht, deshalb warte ich hier lieber auf eine 2te Meinung damit ich nachher nicht alles von neu machen muss


----------



## tröööt (17. Jan 2013)

also ich würde erstmal sagen : falsches forum .. sowas gehört eher ins net oder game forum ... vielleicht ist ja ein mod/admin so nett den thread zu verschieben ...

und solltest du dir eines klar machen : die logik solltest du komplett in den server auslagern ... der client ist nur da die daten vom server graphisch darzustellen und die user eingaben an der server weiterzuleiten ... der client selbst berechnet NICHTS was mit der logik zu tun hat ... das macht NUR der server ...

und mit objekten (in deinem fall in richtung RMI) solltest du dich noch nicht befassen wenn dir die dazu nötigen grundlagen noch fehlen ...

zum punkt multi-thread : ist bei GUI grundsätzlich unabdignbar ...


----------



## Kayuke (17. Jan 2013)

Okay danke erstmal.

Habe nun einen Thread für Server erstellt und klappt auch ganz wunderbar, nun noch etwas, ich habe eine fertige Klasse SinglePlayer, ich würde gerne die Klasse für LAN und SinglePlayer nehmen, da es schöner und effektiver ist.

Geplant hatte ich das ich den SinglePlayer umschreibe und alle Kollisionserkennung etc. mit einem Array von meinem Spielobjekt Helikopter agieren und ich dann im SinglePlayer quasi nur 1 Objekt im array habe und im Multiplayer einfach 2 Objekte reinpacke. Theoretisch richtig?

Ich erweiter den SinglePlayer um einen weiteren Konstruktor so das man diesen aufrufen kann mit 2 Spielobjekten, beim Server erstellen wird dann ein Objekt vom SinglePlayer erstellt und der Client der verbindet sendet mir sein Spielobjekt(Helikopter) an Server und der SinglePlayer greift auf die Klasse Server immer zu und holt sich den aktuellen Stand des Spielobjekts vom Clienten.

So würde ichs jetzt machen wenns möglich ist.


----------



## tröööt (17. Jan 2013)

klar ... is möglich ... aber 1) totaler bullshit 2) schön kompliziert und 3) wäre es saubere einfach noch mal von vorne anzufagen ...

ist leider so wenn man aus einem reinen singleplayer ein multiplayer basteln will das man viel um- und neu-schreiben muss ...
wenn man allerdings gleich plant das es multiplayer werden soll entwickelt man normalerweise erst die server-logik .. und schreibt den client so das er nur anzeige und input ist ... und verbindet beim singleplayer einfach lokal ... und multiplayer dann halt einfach auf den server vom ziel ...

wenn du allerdings die logik im client implementiert und dein server die daten nur austauschen soll ... wirst du sehr schnell 1) starke laggs 2) glitches / bugs 3) cheat möglichkeit und sonstige probleme bekommen ...

das äußert sich dann soweit das du beim jewils anderen entweder zeitlich stark hinterher bist oder an komplett falsch positionen (möglicherweise nicht erlaubte) ...

das alles wird schon nur dadurch vermieden wenn man eine globale instanz (Server) hat ... der dann die daten in sich konsistent hält und sich die laggs nur darauf beziehen das die anzeige etwas verspätet ist und die eingabe bis zum server es mehr latenz hat ... aber das ist dann wenigstens konstant und schaukelt sich nicht auf ...


----------



## Network (17. Jan 2013)

Wie trööt bereits andeutete ist der Client "meistens" in deinem Fall eigentlich immer, nur für die Darstellung der Daten zuständig.
In größeren Spielen inbesondere Strategiespielen mit schonmal bis zu +20.000 Einheiten auf dem Feld, wird dann erst auf andere Möglichkeiten zugegriffen, wie z.B. dass die Clients selbst Daten manipulieren bzw. jeder Client selbst als Server agiert. Solch ein ServerNetz is aber etwas kompliziert zu programmieren und spielt wie gesagt, in deinem Umfang keine Rolle.
Für 2 Spieler funktioniert dieses System ohne Einschränkungen, aber wenn ein dritter oder mehr hinzukommen müsste dafür gesorgt werden, dass sich alle miteinander verbinden und geregelt werden, wer was sendet.

Für ein Mutliplayer braucht man keine externe Serversoftware, die Logik kann man im normalen Clienten mit einbauen, die Clienten müssen sich halt irgendwie darauf einigen wer den Server spielt.
Wobei ich denke, dass dies die Entwicklung des Programmes beschleunigen kann, wenn man den Server outsourced.

Ich weiss jetzt nicht auf welchen Verbindungstyp du dich stürzen willst, aber für Spiele wird normalerweise UDP verwendet. Bei TCP merkt man den lag schon beim senden eines kleinen Textes.

Dann gibt es noch das Problem der Kommunikation. Der Server kennt nun die gesammte Logik und wie wo was warum geschieht, jetzt muss dieser dem Clienten nurnoch verklickern, das Objekt VW an Position XY. Da bietet sich dann bspw. eine HashMap an und irgendein System mit denen jedes Objekt eine einmalige ID bekommt.

Multi-Threading würde ich auf jedenfall befürworten.
Die vorgeschlagene Methode RMI von tröööt auf keinen Fall. Das ist nicht der richtige Anwendungsbereich dafür, würde aber natürlich funktionieren.

Gruß
Net


----------



## Kr0e (17. Jan 2013)

EDIT: Network war schneller  Zu Udp und Tcp... Hier ist oft Irrglaube am Werk. TCP stink heute nicht mehr so arg gegen UDP ab, wie es in den Anfängen war. TCP hat heute enorm clevere Tricks um den Flow schnell zu halten. Langsames TCP liegt meistens am Programmierer! TcpNoDelay ist hier eine Option die UNBEDINGT aktiviert sein sollte!

Auf TCP würde ich nicht verzichten. Ich würde zu einer Mischung raten! TCP für wichtige Infos: Input, Sieg oder Niederlage etc.

UDP für die Rohdaten wie Positionen etc.


Hallo!

Trööt hat schon vieles wichtiges/richtiges gesagt.

Ich würde gerne noch ein wenig mehr ausholen:



Bei professionellen Netzwerkspielen hat der Server stets die Entscheidungsgewalt. Mit anderen Worten: Selbst wenn jemand das Spiel disassembliert und umschreibt, würde er sich nur selbst verarschen, der Server akzeptiert nur korrekten Input! Soviel hierzu!


Ich muss Trööt noch um etwas erweitern: Richtige Spiel-Clienten sind SEHR VIEL MEHR als Bloß Anzeige und Input. Im Gegenteil. Genaugenommen haben Spiel-Clienten GENAU die gleichen Checkroutinen wie der Server. Alles wird auf dem Clienten selbst simuliert und berechnet.

Du denkst jetzt vlt. HÄÄ ?

Der Witz hier ist, dass man damit versucht der Netzwerklatenz entgegen zu wirken. Der Client berechnet im guten Glauben alles selbst und schickt parallel seinen Input an den Server, welcher ebenfalls alles berechnet und updatet etc...

Der Trick ist nun, dass der Server nun natürlich SEINE Sicht der Dinge broadcasted an die Clienten. Jeder Client überprüft dann anschließend:

-->> Hab ichs richtig berechnet ? (Genaugenommen "vorhergesagt" !) 

Im Normalfall sollte der Client 100% das gleiche berechnen wie der Server, abgesehen von Rundungsfehlern.

ABER: Probleme treten bei MultiplayerSpielen auf, weil hier nicht vorhergesehen werden kann, wie sich Spieler verhalten. Ist dir bestimmt shconmal aufgefallen: Wenn bei CSS z.b. 2 Spieler gegeneinander laufen, dann glitch alles so hässlich rum. Hier schlägt die sogenannte "Client Prediction" fehl.

Mit anderen Worten: Der Client wusste nicht, dass der anderen Spieler auch in diese Richtung geht und wumms. Jetzt muss der Client KORRIGIEREN!

Korrektur:
--------------

Das ist knifflich. Man will kein eiskaltes Snapping (Also direkt versetzen). Das würde arg unnatürlich aussehen. Man benutzt hier üblicher Weise eine Mischung aus linearer Interpolation und geschicktem Timing, um den Clienten langsam aber sicher wieder auf "Kurs" zu bringen.


- Stichworte für all diese Techniken: Entity Interpolation, Client side prediction, Lag compensation, Input Prediction.

Alles 1A++ nachzulesen in diesem Artikel !

Sei jetzt aber nicht eingeschüchtert! Das sind Techniken für 3D Egoshooter und andere Zeitkritische Applikationen.

Für ein simples spiel wie du es beschreibst, sollte Entity Interpolation vollkommen ausreichen um es schön flüssig zu machen.

Was ist Entity Interpolation ?
----------------------------

Der Server schickt alle 33ms z.b. die Position der Spielobjekte. 33ms sieht aber ruckelig aus. Hier wartet man ab, bis der erste und zweite Wert ankommt und interpolatiert dann zwischen diesen Werten linear.

Viel Erfolg!

PS: Bei konkreten Fragen, schreibe mir eine PN.

Achso, hier ist ein Bomberman Netzwerkspiel, welches ich vor einiger Zeit für die Uni schreiben musste. Ist in Java geschrieben, vlt hilfts dir  Kannst jedes Fitzel Code daraus Frei Haus verwenden 

https://github.com/chrisprobst/gruppe33


----------



## tröööt (17. Jan 2013)

naja ... um dir ein bisschen den wind aus den segeln zu nehmen : die GoldSrc (Half-Life) oder Source (Half-Life 2) Engines wären jetzt auch meine besten beispiele gewesen ... vor allem da ich mich in diesem "universum" verdammt gut auskenne ...

und in punkto interpolation weis ICH auch bescheid ... und habe mich ja schon mit befasst ... nur hab ich davon nichts erwähnt da mir das dann für das was TO geschrieben doch etwas zu weit geht ...

klar ist eine reine anzeige und weiterleitung von input die einfachste art eines clienten ... z.b. einfaches TelNet bei nem MUD ... aber das das heute nicht mehr ausreicht und eigentlich viel vom client übernommen und lediglich mit den daten vom server abgeglichen und korrigiert wird ist mir bewusst ...

da mach dir um mich mal eher weniger sorgen als darum wie wir das TO erklären ...
gut .. auch wenn ich jetzt im game-design nicht der beste bin kenn ich mich mit netzwerk-krams doch recht gut aus ...

war auch in nem projekt zeitlang verantwortlicher für net-code ... musst dafür extra n bissl C lernen ... hab davon aber auch schon wieder die hälfte vergessen ...


und um noch mal auf network und den angesprochenen tcp-lagg zu kommen

ich hab mal schiffe versenken mit tcp geschrieben ... und das hatte im LAN n 3sek lagg ... hab dann einfach den net-code gegen ne UDP variante getauscht ... und hatte weniger als 5 ms (laut java) verzögerung ...

also da ist schon was dran ... allerdings wird TCP parallel als steuer-daten kanal genutzt um halt wichtige infos die nicht zeitkritisch sind auszutauschen ...


----------



## Kr0e (17. Jan 2013)

tröööt hat gesagt.:


> ich hab mal schiffe versenken mit tcp geschrieben ... und das hatte im LAN n 3sek lagg ... hab dann einfach den net-code gegen ne UDP variante getauscht ... und hatte weniger als 5 ms (laut java) verzögerung ...




3Sek Laaag ist ein Programmproblem und nicht mit TCP so direkt in Verbindung zu bringen. Wenn soooviel Ahnung in diesem "Universum" hast, dann wundert mich diese Aussage. Kennst du setTcpNoDelay ??

TCP Tuning wäre hier ein Stichwort. Es gibt zich Kniffe um TCP schneller zu machen.

Aber klar. UDP da anwenden, wo es Sinn macht. TCP führt nämlich manchmal unnötigen Protokoll Overhead mit. Aber wir Leben in Zeiten, wo jeder min. DSL 2000 haben sollte. Und von Lan, müssen wa gar nicht erst Reden. TCP ist im LAN praktisch vergleichbar mit UDP was Latenz und RTT angeht.



PS:

war auch in nem projekt zeitlang verantwortlicher für net-code ... musst dafür extra n bissl C lernen ... hab davon aber auch schon wieder die hälfte vergessen ...

Willst du jetzt nen Keks ?


----------



## tröööt (17. Jan 2013)

ich bezog mich mit "universum" auf Half-Life ... nicht auf das was mit java netzwerk-mäßig möglich ist ...

und ja : mir waren solche "tricks" durchaus zu der zeit bewusst um die TCP-latenz zu reduzieren ... nur trotzdem schon komisch das es einen solchen unterschied machen ob man mit TCP und streams arbeitet oder mit UDP-Datagrammen ...

und zum keks : kannst mir gerne einen mailen ... die aussage war eigentlich mehr informativ das ich mich mit dem was hier gefragt wurde doch schon etwas intensiver beschäftigt habe ...


----------



## Kayuke (18. Jan 2013)

Danke erstmal für die zahlreichen Antworten 
Zurzeit klappt noch garnix, ich habe eine Server Verbindung hergestellt und Integer ausgetauscht aber dann habe ich versucht einen KeyListener zu übertragen vom Clienten zum Server, also das wenn Client Pfeiltaste nach oben klickt, soll das beim Server ankommen.

Den SinglePlayer habe ich jetzt komplett umgebaut, dieser wird mit einem Array Helicopter aufgerufen und so kann wenn nur eine Instanz im Array ist im SinglePlayer gespielt werden und wenn da mehrere sind werden diese gezeichnet, kollisionen geprüft usw.


----------



## tröööt (18. Jan 2013)

hmmm ... klar kann man zu ActionListener auch Serializable implementieren ... aber wenn man das über n ObjectStream schickt hat das wenig sinn ... hier müsstest du dann schon RMI nutzen damit das auch "live" bei jeweils anderen ankommt ...

alles in allem aber gehe ich immer noch von einem sehr schlechten design des code aus


----------



## Kayuke (25. Jan 2013)

Okay es schaut so aus, mit RMI hab ichs nicht hinbekommen, stattdessen hab ich TCP genommen und beim socket (clienten) .setTcpNoDelay aktiviert. 

Es ist fast perfekt, es ist sone halbe Sekunde Verzögerung wenn ich übers Netzwerk spiele, merkt man nur bei der Steuerung.
Ich übergebe über TCP vom Server zum Clienten einen String und vom Clienten zum Server einen String.

In diesem String stehen alle Informationen und mit RegEx hole ich mir die einzelnen Informationen dort raus und verarbeite sie.
Auf keinen Fall eine schöne Lösung aber ist auch mein erstes Java Projekt und wenigstens läufts jetzt.

Gibts noch irgendwas das ich versuchen kann damit die Verzögerung geringer wird wenn der Client seinen String mit Tastatureingaben an den Server schickt ? UDP scheint ja kaum schneller zu sein heutzutage :/
Vlt noch irgendein Trick? Immerhin verschick ich eigtl. nur einen String vom Server zum Clienten und dieser einen zum Server dauerhaft, das muss doch schneller gehen


----------



## tröööt (25. Jan 2013)

doch doch ... das zauberwort heißt hier schon sehr wohl UDP ...

um den unterschied zwischen TCP und UDP vielleicht nur kurz anzureißen : TCP ist ein STREAM der sicherstellt das ALLE daten in der richtigen reihenfolge ankommen und lässt sich dies bestätigen ...
UDP hingegen sendet einfach die datagramme und fertig ... keine reihenfolge ... keine prüfung ob erfolgreich oder sogar mehrfach angekommen ... nichts ... außerdem in der regel meist weniger information als TCP

es wäre also durch aus schneller im actionlistener ein UDP-datagram auf die reise zu schicken (dabei sollte nur die aktuelle steuer-information dynamisch sein und der rest des paketes wie ID und sowas schon vorher in nem string vorgehalten werden) und beim server einfach auf dem UDP-socket schön receive() callen ... das sollte im LAN die latenz deutlich reduzieren ...
über den TCP-kanal werden dann nur steuer-informationen und gelegentlich informations-updates übertragen ... aber die echtzeit-kommunikation sollte über UDP laufen ...


das du RMI nicht auf die reihe bekommen hast war mir vorher schon klar ... ist kein einfaches thema ... und auch viel zu langsam für sowas ... es war nur mal angerissen erwähnt


----------



## Kr0e (25. Jan 2013)

Keine Ahnung wie es bei RMI ist (veraltet, langsam, etc) aber Tcp + setTcpNoDelay gibt bei mir ähnliche Latenzen wie Udp im Lan. Versuch mal richtiges Tcp und nicht dieses RMI Gedängel.

Udp macht erst Sinn, wenn du wirklich zeitkritische Daten hast und du das allerletzte bisschen rausholen willst. Ein Egoshooter, wo der Spieler auf die ms aimen und treffen will (hierzu sind wie oben erwähnt zig andere Techniken neben Udp von Nöten) benötigt definitiv Udp. Im Lan ist das im Übrigen so oder so egal.
Die Leute sind sich oft nicht bewusst wie fix das LAN ist. Wenn TCP im Lan zu langsam is, liegt es zu 99% am Programmierer und zu 1% an einem miesen Router/Switch/Hub.

Tcp ist wie erwähnt ein STream. Sprich es wird alle x-Bytes eine Kontrolle gestartet, ob alles da is. Bei hohen Latenzen, wie im Internet manchmal (DAs ist aber dank DSL 6000+ schon arg zurück gegangen) anzutreffen, is das natürlich spürbar.

Aber im Lan merkst du davon nichts, da du meist Latenzen < 2-3ms hast.


----------



## Kayuke (25. Jan 2013)

Ok danke, was versteht ihr unter richtigem TCP und nicht diesem RMI gedängel?

Ich poste einfach mal meine Verbindung die ich aufgebaut habe, vlt. sieht jemand sofort wie mans besser hinkriegt ohne das ich auf UDP umsteigen muss.

EDIT: ich weiß das ich sämtliche .close der Verbindungen unten ignoriere bzw. entfernt habe und es somit Exceptions schmeißt wenn die Verbindung aus ist, es geht mir aber zurzeit nur darum das das Spiel Synchron ist mit wenig Aufwand, weil ich leider gerade wenig Zeit habe.

Server.java

```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server extends Thread
{
	// Deklaration
	private final ServerSocket server;
	Socket client = null;
    ObjectInputStream objectInputStream=null;
    String serverInfos = "Testpaket";
    String clientInfos;

	// Konstruktor
	public Server(int port) throws IOException
	{
		server = new ServerSocket(port);
	}
	
	// Run Methode überschreiben
	@Override
	public void run() {
		while (true) 
		{
			try {
				client = server.accept();
				if (client.isConnected()){
					handleConnection(client);
				}
			} 
			catch (IOException e) 
				{
					e.printStackTrace();
				} 
			}
	}
	
	private void createServerInfosString(){
		// Erstelle String für den Clienten mit allen Infos
	}
	
	
	public void updateCopter2(String updateInfos){
		// Nutze Infos des Clienten für Copter 2 (Tastatureingaben)
		System.out.println("Server empfängt: "+updateInfos); // zum testen
	}
	

	
  private void handleConnection(Socket client) throws IOException
  {
	  PrintWriter pw = new PrintWriter(client.getOutputStream(), true);
	  BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));

	  while(true){
		createServerInfosString(); // Erstelle Infos für Clienten
	 	pw.println(serverInfos); // Sende zum Clienten//
	 	updateCopter2(br.readLine()); // Empfange und verarbeite Tastatureingaben vom Clienten
	  }
  }
}
```


Client.java

```
import java.net.*;
import java.io.*;
class Client extends Thread
{
	Socket server = null;
	InputStream input;
	String host;
	static public String clientInfos = "Test";
	static public String serverInfos;
   
	
	
	public Client(String host){
		this.host = host;
	}
	    
	
	@Override
	public void run(){
		while(true){
			try
		    {
				  server = new Socket(host, 3141);
				  server.setTcpNoDelay(true); // Verschnellern
				  if (server.isConnected()){
					  handleConnection(server);
				  }

		    }
		    catch ( UnknownHostException e ) {
		      e.printStackTrace();
		    }
		    catch ( IOException e ) {
		      e.printStackTrace();
		    }
		}
	}
	
	
	private void handleConnection(Socket server) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(server.getInputStream()));
		PrintWriter pw = new PrintWriter(server.getOutputStream(), true);
	    
		  while(true){
			  	pw.println(clientInfos); // Versende Tastatureingaben
				System.out.println("Client empfängt: "+br.readLine());	// Empfange Informationen vom Server
			  }

	}
}
```


----------



## Network (25. Jan 2013)

RMI ist eine Technologie/Protokoll entworfen damit ein Javaprogramm die Methoden eines anderen Javaprogrammes aufrufen kann.
Tröööt hatte das erwähnt, weil er meinte es würde sich um eine alternatives Protokoll zu TCP/UDP handeln in deinem Fall. Einfach nicht beachten  RMI ist echt cool aber mittlerweile gibts einfach weitaus bessere externe Lösungen, RMI ist halt in der Standardlib enthalten und kostenlos.

Also einfach nicht beachten (es sei denn es interessiert dich), man stellt so eine Verbindung auch ganz anderst auf.

Gruß
Net


----------



## Kayuke (25. Jan 2013)

Danke @Network aber gibts den nix was ich am obigen Code verbessern kann damit diese 1ne Sekunde Verzögerung weg ist? 

Ansonsten werd ich wohl dasselbe nochmal in UDP versuchen.


----------



## tröööt (25. Jan 2013)

nun ... TCP_NODELAY ist dafür verantwortlich den sog. "Nagle-Algorithmus" zu deaktivieren ...
dieser Algorithmus ist einfach erklärt :
volles TCP-paket : direkt senden
nicht volles TCP-paket : erst senden nach dem ALLE bestätigungen vorangegangener pakete eingetroffen sind
sind und zweck ist es den header-overhead zu verringern wenn man nur wenige daten in ein TCP-paket steckt ... denn gerade bei Ethernet muss ein ether-frame mindestens 64byte lang sein

setzt man also TCP_NODELAY so werden UDP-ähnlich die TCP-pakete direkt versendet oder auf bestätigung des vorheringen zu warten ... was normalerweise die geschwindigkeit erhöt ...

dein problem dürfte vermutlich einfach in der sache der natur liegen : TCP ist grundsätzlich ein langsameres protokoll als UDP ... und je nach dem wie lange du in deinen methoden brauchst um den inhalt des Paketes zusammenzubauen erzeugt das schon lagg ...
außerdem ist dein loop sub-optimal da du nach dem senden von informationen direkt wieder liest ... was auch noch mal zeit kostet wenn die daten von der gegenstelle noch nicht vollständig angekommen sind ...

außerdem arbeitest du mit BufferedReader/Writer ... das erzeugt zusätzliche latenz da halt die daten erstmal gecached und dann auch noch durch einen charset gejagt werden ... sind zwar nur ein paar ms die da höchstens anfallen ... aber das summiert sich alles ...

auch ist es schlecht in den beiden threads die fürs lesen/schreiben verantwortlich sind die update-methoden des spiels direkt zu callen statt in einem seperaten thread laufen zu lassen um so schneller wieder fürs netzwerk verfügbar zu sein ...


siehst also : es ist nicht nur TCP was da bissl bremst ... es liegt auch viel an schlecht strukturiertem code der sich selbst ausbremst ... und da wird dann auch UDP nicht wirklich viel helfen ...


----------



## Kayuke (25. Jan 2013)

Joa habs jetzt doch sehr akzeptabel hinbekommen 

Die Server und Client Schleife versenden jetzt immer genau einen String und empfangen einen, die Verzögerung derzeit ist kaum noch merkbar, gerade mit nem Kollegen ne halbe Stunde lang gespielt 

Damit bedank ich mich mal bei euch allen 
Auch ein besonderes Danke Schön an trööööt der sehr aktiv mitgeholfen hat und mir einiges an Verständnis in der Netzwerkprogrammierung gegeben hat


----------



## Kr0e (26. Jan 2013)

Wieder einmal kann ich nur 50% zustimmen. TCP ist ein langsameres Protokoll ? Auf was beziehst du dich ? Langsamer = Wie viel langsamer ? Deine Formulierungen sind zwar streng genommen korrekt, lassen aber bei der Interpretation einigen Spielrauf für negative Einschätzungen. TCP hat ein paar Byte mehr Headerdaten (Haha, ein paar Byte...) und durch den Stream gibt es alle x-Byte eine Kontrolle über Erhalt der Daten, welche aber groß genug gewählt werden kann, womit nur selten Daten geprüft werden und im lan ist der Verlust von TCP Paketen ohne vollast gleich null.

BufferedReader und Writer sollen in Verbindung mit TCP mehrere-ms Lags verursachen ? Ich finde deine Aussagen teilweise oft stark überzogen und würde da ohne jeglichen Beweis durchaus Zweifel haben.

"Ein paar ms"... Ich wette du kannste mehrere MB durch BufferedWriter/Reader jagen ohne dass du da 50 ms erreichst, von Initialisierungs-Delays mal ganz abgesehen.


Fakt ist: Langsam = Schlechter Algortihmus/Code. Ein mieses Conzept ist auch mit C++ ein mieses Konzept. Und ein gutes Konzept dürfte selbst in einer derart Overheading Sprache wie Python ein gutes Konzept sein und an TCP liegt es in den meisten Fällen nicht ! DENN! Wie viel MB gedenkst du denn übers Netz zu jagen ? Das sind höchstens ein paar Kilobyte bei einem Spiel und wie ich anfangs sagte:

Latenz ist sowieso da und richtige Spiele haben sowieso Konzepte um Lags zu kompensieren.
SPRICH: Wenn du 100 ms Latenz mit Udp und vlt 150ms mit TCP hast.... Das ist beides relativ viel ohne Kompensation. Genau deshalb gibt es ja diese ganzen Faxen wie es die Source Engine im Extremen macht. Bei Source können Spieler mit einer Ping bis 800 noch korrekt bedient werden... Warum nimmt Source UDP ? Weil UDP ein gutes Konzept hier ist. Es treffen alle 33ms Pakete ein und somit wäre es egal, wenn was verloren geht. Es geht hier weniger um Performance als ums Konzept. Warum TCP wenns, nicht nötig ist. Aber zu sagen: TCP, MEGA LAG ist einfach nur falsch und kommt immer auf den Fall an. UDP kommt heute neben VoIP/Videostreaming & Games sowieso nur noch selten zum Einsatz.


@TO:

Lass dich hier nicht allzu stark von TCP abbringen. Man sollte auf diesem Bereich eh viel selbst testen um sich selbst ein Bild davon machen zu können. setTcpNoDelay ist hierbei der häufigste Anfängerfehler. Testen, Testen und nochmal Testen!


----------



## Kayuke (26. Jan 2013)

Ich habe testweise einen UDPServer und UDPClient gebastelt aber nicht ans Spiel angepasst sondern einfach Pakete verschickt und gemessen wieviele / wie schnell und das selbe mit TCP mit der Funktion setTCPnoDelay, war kaum ein Unterschied weshalb ich TCP gelassen habe und versucht habe den Code zu reduzieren der verschickt wird, bzw. es schöner zu verschicken.

Nun hat man ca. würde sagen 200 MS Verzögerung wenn man ne Taste als Client klickt, das ist zwar leicht spürbar aber spielbar und ich bin mir sicher das das auch mit TCP behebbar wäre wenn ich noch weiter rumprobieren würde 

Aber mir reicht das erstmal so, jetzt erstmal Bugs entfernen und Exceptions abfangen :>


----------



## trööt (27. Jan 2013)

ist zwar richtig das bei heutiger technik der unterschied zwischen tcp und udp zu vernachlässigen ... der grund bleibt aber : während bei udp lediglich datagramme im netzt verteilt werden hängt bei tcp noch einigens mehr hinten dran ...

klar kann man diesen effekt mit brutaler rechenpower kompensieren ... aber das grundproblem damit nicht lösen


----------

