Router kaputt?, und Daten Übertragung

Hey Leute.
Also ich hatte ja vor ein paar wochen diesen Thread eröffnet.
Da ich zu der Zeit mit OpenGL anfing, rückte das etwas in den Hintergrund. Jedenfalls, da ich das mal soweit abschließen will, öffne ich gerade das Programm, und… es klappt.
So wie es immer sein sollte. Nach dem eben genannten Thread hatte ich noch eine Woche lang jeden Tag geguckt obs geht, nichts. Und jetzt… auf einmal klappts…
Da hat doch der Router ein Problem oder? Was meint ihr?

Zur anderen Sache: Jemand meinte mal er würde die Daten immer als bytes[] schicken und dann konvertieren in das was er braucht.
Ist das performanter / Besser / etc als die Sachen als Strings zu schreiben? Ich müsste doch zum Beispiel für einen String immer wieder new String(bytes[], “UTF-8”) schreiben…
ist das nicht unnötiger aufwand für den Gc? (Es geht ja um ein Spiel…) Wie macht ihr das?

Mfg

kann sein dass bei so einem unspezifischen Problem der Router was damit zu tun hat oder auch tausend andere Stellen,

und nicht böse nehmen wenn man wie so oft zumindest auf den Gedanken kommt, dass das größte Problem auf dem Stuhl vor dem Rechner sitzt, Spaß muss sein :wink:


Daten werden sowieso immer und überall nur als bytes gespeichert und übertragen, kommen in Java in dieser reinen und einzigen Rohform,

zu String-Objekten müssen sie immer interpretiert werden,
wenn man den Standardmechanismen wie Reader-Klassen nicht genug (zu-)traut, kann man da manches selber übernehmen

im einfachen Fall ohne konkreten Grund sollte man aber wie immer Performance-Fragen hintenanstellen,
ein guter Teil an ‚Optimierungen‘ optimiert gar nicht erst oder schafft ganz andere Probleme,

freilich kann man sich auch andersrum mit etwa Reader-Klassen ewig rumschlagen während es anders schneller ginge

Zum Thema Reader/Writer/Characters/Strings oder Bytes/Streams. Ganz einfach: wenn Du wirklich Zeichendaten verarbeiten willst, dann nimm Reader/Writer. Wenn du das nicht willst Streams. Ich habe den Code in dem anderen Thread kurz überflogen. Habe nur die Stelle gefunden, wo Du Math.random() + "
"
versendest. Da ist es in der Tat unnötig, das als String zu tun. DataInput-/OutputStream (http://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html) wäre hier die passende Wahl. Der nimmt Dir das Konvertieren der rohen bytes in die entsprechenden Javatypen ab.

Wenn du allerdings an anderen Stellen auch mit wirklichen Strings arbeitest (also nicht nur Zahlen), dann kann es bequemer sein, alles über Reader/Writer zu machen. Das habe ich in Deinem Code aber auf die Schnelle nicht gefunden.

Nun ja das kskb versemdet nur zahlen stimmt, aber in meinem programm wird die position als string “000,000” versendet. Da ich bei der initialisierung aber auch sowas wie farbe mit schicken will, ist ein string dort wirklich angebrachter denke ich… oder nicht?

es ist eine praktische Angelegenheit,
man denke nur an drei Buchstaben die eine ganze Welt bedeuten: XML,
oder 4 Buchstaben HTML, aber XML ist noch allgemeiner als Datenaustauschformat,
strukturierte Nachrichten, für Menschen auch gleich lesbar, in Datei speichern usw.,

auch ohne XML-Tags einfach nur Infos hintereinander, Position, Farbe, Richtung, absolut geeignetes Format,

aber so eine Nachricht kann schnell 200 Byte brauchen während die zugehörige Information optimal verpackt auch in 30 Bytes passen könnte,
es geht optimaler, für Extremansprüche kann man drüber nachdenken, aber Text-Nachrichten empfehlenswerte Sache, ja

(dachte am Anfang an etwas anderes Thema)

edit: Programmiersprachenunabhängigkeit kommt dazu bei Txt, was aber bei Java zu Java nicht unbedingt der Fall sein muss

Naja, ob man sich nun um optimierung gedanken machen sollte oder nicht, bei nem hyper schnellen austausch von daten (wie es bei nem spiel nun mal sein muss) gilt es die groesse kompakt zu halten. Frage ist nur, sollten man vielleicht beides verwenden, jenachdem wo es passt?

Theoretisch wäre das möglich. Aber auf Empfängerseite ein Problem, die Daten auseinander zu halten. Wenn Du alles über am Ende den selben Socket-Stream sendest. Woher soll der Empfänger wissen, ob er gerade die Positionsdaten als int, die Farbe als 3 vorzeichenlose bytes oder sonstwas als String lesen soll? Da wird man sich sicher so eine Art Miniprotokoll überlegen, wo es Keys oder oder sowas gibt, etwa so: position=20,50 farbe=FFCC00. Dann weiß der Empfänger sicher, was der da gerade bekommt. Das geht nur mit Strings, also zeichenbasiert, also Reader/Writer. Wenn Du natürlich in der Lage wärest, alles als Zahlen zu kodieren und/oder die Reihenfolge, in der was kommt, sicherstellen kannst, ginge das auch byte-Basiert mit Streams. Am Ende ist die Antwort wie immer: „Kommt auf den Anwendungsfall an.“

Stimmt wohl, das würde angesichts dieses kleineren Projekts leicht overkillig werden.
Dann bleib ich wohl erstmal bei Strings, weil es wohl am erweiterbarsten ist.
Der Ablauf soll später so aussehen:
Nachdem der Socket mit accept() angenommen wurde, muss er ein paar sachen schreiben,
darunter “name”, “color”, evtl zusatzinformationen wie flagge, spieler id oder sonstiges. (Letzteres nur theoretisch)
Dann erst wird der Socket in die “Lobby” gepusht, und erst wenn diese voll ist startet das Spiel und die Highspeed übertragung beginnt…

Naja ich guck mal was sich machen lässt.
Danke euch!

[OT] Slater… das wollt ich dich schon immer mal fragen… Wie siehts bei dir eigentlich mit Punkten… Fragezeichen oder Ausrufezeichen und / oder so… aus? xD [/OT]

Fragezeichen setzte ich immer wenn ich ne Frage stelle, oder nicht? :wink:

So ein Blödsinn. Mit Strings ist es einfach und zudem noch „lesbar“. Aber es geht auch ohne weiteres ohne…

Man überlege nur mal was für einen Overhead mein SIMON hätte wenn ich alles mit Strings beschreiben müsste…

Was man mit Strings vielleicht so machen würde …

position=20,50 farbe=FFCC00

… könnte man mit nackten Bytes so machen (der Lesbarkeit wegen in Hex nieder geschrieben):

0x00 0x14 0x32 0x01 0xff 0xcc 0x00

Erklärung:

Einleitend gibt es immer ein byte das Beschreibt was folgt.

Angefangen wird mit 0x00, was in diesem Fall eine Position beschreibt. Hier wurde angenommen dass die x/y Position sich durch je ein Byte beschreiben lässt. Auch int (wären dann je 4 bytes) oder long (je 8 bytes) wären ohne weiteres möglich.
Nach dem „Tag“ 0x00 für "jetzt kommt eine x/y Position, kommen wie gesagt die x (0x14) und y (0x32) Position.

Da Positionsdaten in diesem Beispiel immer aus insgesamt 2 bytes bestehen, muss das nächste Byte das nächste „beschreibende“ Byte folgen: 0x01
Das steht in diesem Fall für "jetzt kommt eine RGB Farbe. FFCC00 wird hier dann zu 0xff, 0xcc und 0x00. Da RGB Farbangaben immer aus 3 bytes bestehen passt das so.

Wenn man etwas „dynamisch langes“ verschicken möchte, z.b. einen String, könnte man das so „codieren“

0x02 Als markierung für einen String
0x00
0x00
0x00
0xA0 Vier bytes als Integer. Hier 0x00, 0x00, 0x00 0xa0 = länge von 10
0x
0x
0x
0x
0x
0x
0x
0x
0x
0x ein 10 Zeichen langer String, byte für byte

Aber um auf das Eingangsbeispiel zurück zu kommen:

position=20,50 farbe=FFCC00 ----> 27 Bytes
0x00 0x14 0x32 0x01 0xff 0xcc 0x00 ------> 7 Bytes

Selbst wenn man die X/Y Position jetzt nicht mit Byte sondern mit Integer senden würde, wäre man noch deutlich unter 27 Bytes:
9 + fehlende 2x3 bytes = 13 statt 27 wie bei String… Zumal das String-Beispiel noch viel länger wird wenn man anfängt eine Integer-beschriebene POsition mal „auszureizen“. Denn da kann der längste Integerstring (-2147483647) 11 Zeichen lang werden. Mit Integer als byte ist und bleibt es bei 4 byte.

Das SIMON Protokoll sieht übrigens (vielleicht hilfts jemandem) so aus:

  1. Byte: Beschreibt die Art der Nachricht. Also „Platz“ für 256 verschiedene Nachrichtenarten im Protokoll
  2. bis 5. Byte: Vier Byte Integer-Wert. Damit verpasse ich jeder Nachricht eine Sequenz-Nummer um Request-Response zusammen finden zu lassen
  3. bis 9. Byte: Vier Byte Integer-Wert: Gibt die Länge der Nachfolgenden Nachricht an. Somit weiß ich beim lesen aus dem Stream wieviele Bytes ich noch lesen muss um die Nachricht für die weitere Verarbeitung in einen Worker-Thread stecken zu können, ohne die ganze Nachricht gleich parsen zu müssen.
  4. bis x. Byte: Die eigentliche Nachricht. Die Wahl der Verarbeitungsroutine wird am ersten Byte (Art der Nachricht) fest gemacht.

Damit habe ich einen „Protokolloverhead“ von lediglich 9 Bytes. Mit geschicktem Threading und Java NIO erreiche ich so in Extrem-Tests einen Nachrichtendurchsatz von fast 38.000 Nachrichten pro Sekunde auf Serverseite.

Werbung kostet 12 Cent pro Posting und Viewer :wink:

ne, ist schon informativ, aber etwas spät, und Bezug zu Simon, nunja :wink:

[QUOTE=SlaterB]Werbung kostet 12 Cent pro Posting und Viewer :wink:

ne, ist schon informativ, aber etwas spät, und Bezug zu Simon, nunja ;)[/QUOTE]

Es ging doch um die Sache mit dem Protokoll… SIMON ist da wurscht. Aber das Protokoll ist ohne weiteres auch auf andere Szenarien anwendbar.

Eine Art „Message-ID“ braucht man eigtl. immer. Und die Länge der Nachricht im Header zu haben ist auch nicht verkehrt. Die Sequenz-ID… Nun ja. Da kann man sich ja eine Art Protokollprüfsumme reinbasteln, damit das hacken des Protokolls „schwieriger“ wird…