Sockets und Datenströme

starbuck86

Mitglied
Hallo Comm.

Ich habe ein Problem und finde einfach keine Lösung.

Ausgangssituation:
Ich habe ein Serverprogramm, das Datenpakete (Form: "abc:123:k2ddds:eek:fk8: -") via Socket an seine Clients senden soll. Dazu verwende ich einen PrintWriter. Es gibt von den oben genannten Datenpaketen etwa 100 Stück, die alle in einem Stack liegen und abgearbeitet werden. Das Senden an sich läuft als eigenständiger Thread in einer run()-Methode - solange, bis der Stack abgearbeitet/leer ist. Wichtig: Jedes Datenpaket muss einzeln gesendet werden.
Java:
run() {
while (!s.empty()) {
			String x = (String)s.pop();
			System.out.println(x+" -");
			pw.println(x+" -");
			pw.flush();
			try { this.sleep(300); } 
                          catch (InterruptedException e) { e.printStackTrace(); }
		}	
...
}

Auf der anderen Seite gibt es den Client, der sich eines InputStreamReaders bedient. Er kann die oben genannten Datenpakete immer nur einzeln verarbeiten. Also es darf niemals folgendes gesendet werden: "abc:123:k2ddds:eek:fk8: -dbc:123:k2ddds:eek:fk8: -". Doppelte Datenpakete gehen gar nicht.
Java:
while (true) {
			        int anzahlzeichen = 0;
				anzahlzeichen = in.read(buffer,0,100);
				String eingabe = new String(buffer,0,(anzahlzeichen-1));
                                try { Thread.sleep(20); } 
                                  catch (InterruptedException i) { i.printStackTrace(); }
                }

Meine Lösungsansätze:
Ich habe diesen Stack erst kürzlich eingeführt. Vorher habe ich einfach direkt die Daten versendet in einer Schleife im Hauptprogramm und habe eine Verzögerung reingemacht mit Thread.sleep(270). Mit diesem Wert kamen alle Datenpakete einzeln beim Empfänger an.
Mit Stack inkl. run() funktioniert das aber irgendwie nicht mehr. Ich habe so das Gefühl, dass dieser Thread - je länger er läuft - immmer schneller wird. Dieses sleep(300) wird irgendwie am Ende gar nicht mehr ausgeführt - allerdings auch keine Exception geworfen.

Das ganze sieht dann so in etwa aus (Die Zahlen in den Rauten grenzen ab, was auf einmal beim Client angekommen ist, bzw aus dem InputStreamReader auf einmal ausgegeben wird.):
#126# file:test:09:ascasc:available: -
file:test:01:cassac:available: - #126#
#127# file:test:99:csacsa:available: - #127#
...
#135# file:prod:99:casascascsa:search: -
file:prod:01:pS:search: - #135#
#136# file:prod:01:CHEMINFORMRX:search: - #136#
...
#144# file:beta:07:dhfdfghf:search: - #144#
#145# file:beta:07:fghfgh:search: -
file:beta:09:fghfgh:search: - #145#
#146# file:beta:07:fghfgh:search: - #146#
#147# keepalive - #147#

Hat jemand eine Idee, wie ich es hinbekomme, dass alle Datenpakete vom Server einzeln gesendet und beim Client einzeln empfangen/verarbeitet werden? Bzw wo mein Engpass ist?

Danke && Gruß
Thomas
 
"Pakete" in dem Sinne, wie du sie benötigst kannst du nicht direkt schicken. Wenn du etwas über deine Netzwerkkarte schickst, wird es einfach gebündelt weitergeleitet (sofern sich der Zielhost nicht ändert).

Ich würde vorschlagen, deine Messages mit einem eindeutigen Seperator zu trennen.
Eigentlich fast genau so, wie du es in deinem letzten Zitat bereits händisch gemacht hast:

Code:
#file:test:09:ascasc:available: -$
#file:test:01:cassac:available: -$
#file:test:99:csacsa:available: -$
...
#filerod:99:casascascsa:search: -$
#filerod:01:PS:search: -$
#filerod:01:CHEMINFORMRX:search: -$
...
#file:beta:07:dhfdfghf:search: -$
#file:beta:07:fghfgh:search: -$
#file:beta:09:fghfgh:search: -$
#file:beta:07:fghfgh:search: -$
#keepalive -$

Wenn du jetzt im Client-Programm die empfangenen Packets durchgehst, musst du einfach nur gucken, wo die nächste Raute (#) losgeht (sofern die Raute ein eindeutiges Zeichen darstellen kann). Das Endezeichen ($) ist auch sinnvoll, damit du bei jedem Teil auch siehst, ob es bereits fertig übertragen wurde (sofern das Dollarzeichen bei den Nachrichten auch eindeutig ist).

Es kann durchaus vorkommen, dass ein richtiges Daten-Paket unter Umständen folgenden Aufbau hat:

Code:
Datenpaket Nr-4711:
#file:test:09:ascasc:available: -$#file:test:01:cas

Datenpaket Nr-4712:
sac:available: -$#file:test:99:csacsa:available: -$

TCP/IP-Datenpakete haben gewöhnlicherweise eine Größe von 1452 Bytes für Nutzdaten (http://de.wikipedia.org/wiki/Transmission_Control_Protocol#TCP-.2FIP-Paket-Gr.C3.B6.C3.9Fe). Das heißt, jede Nachricht wird nach 1452 Zeichen abgeschnitten und für den restlichen Inhalt ein neues Datenpaket verwendet.

Ich hoffe ich konnte dir damit ein wenig erklären, wie die Pakete übers Netz wandern und wie du diese Parsen musst!

Viele Grüße,
MAN
 
Ok. Ich versuche das gerade umzusetzen.

Weisst Du wie das Zeichen heisst, das als letztes in einem TCP-Paket im Datensatz drinsteckt?

Das macht mir jedesmal eine Newline, und ich muss abfragen an welcher Stelle das Zeichen kommt. Dass ich zB ein replace() geben kann.
 
Zurück