Entwickler-Ecke

Internet / Netzwerk - Indy TCPServer String lesen mit unbekannter Länge


ttobsen - Do 25.08.05 23:49
Titel: Indy TCPServer String lesen mit unbekannter Länge
Hi

Ich schreibe gerade eine kleine TCP Anwendung welche über TCP mit einem PHP Script kommuniziert.

Das Script sendet folgende Daten (als String) an meinen Server:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy--------------------...

Die x-en und y-e stellen jeweils einen 32 Byte Block dar (darin wird ein md5 hash übergeben). Das Problem sind die ---. Diese können je nach Eingabe des Users unterschiedlich lang sein.

Die ersten 32 byte Blöcke les ich so aus:


Delphi-Quelltext
1:
2:
BlockX:= AThread.Connection.ReadString(32);
BlockY:= AThread.Connection.ReadString(32);



Doch wie les ich nun den letzten unbestimmten Teil am elegantesten aus.

Die erste Variante war das das PHP Script den String ausfüllt (zum Beispiel mit leerzeichen) bis er eine vorher bestimmte Bytezahl erlangt. Dies ist jedoch sehr unflexibel.

Die zweite Variante war:


Delphi-Quelltext
1:
2:
3:
4:
repeat
TempChar:= AThread.Connection.ReadChar;
KomplettString:= komplettString + TempChar;
until TempChar = '';



diese Variante schlägt leider auch fehl (ReadChar liefert manchmal auch '' (leeren String) zurück, somit bricht die Schleife zu früh ab).

Die 3te Variante war das ich folgende Daten sende:

xxxxx...yyyyy...ZZZ--------------------------

wieder 2x 32Byte an Daten, danach 3Bytes Zahlen in einem String, darin steht dann die länge der unbetsimmten Daten (durhc den - gekennzeichnet), welche ich dann auslesen kann. Das wäre im Prinzip her ganz easy, weil ichs total leicht auslesen könnte:


Delphi-Quelltext
1:
2:
3:
4:
BlockX:= AThread.Connection.ReadString(32);
BlockY:= AThread.Connection.ReadString(32);
ZZZInteger:= StrToInt(AThread.Connection.ReadString(3));
UserMessage:= AThread.Connection.ReadString(ZZZInteger);


(darauf bitte keine einwände, natürlich kann ich die Zahlen als Integer speichern, wofür ich bei 255 Zeichen nur ein Byte bräuchte, das ändert aber nichts an meinem Beispiel)

Doch da gibt es das Problem das man ohne Probleme die Daten patchen kann und somit den Server aufhängen kann. Ein User könnte zum Beispiel im Z Block schreiben: 100, dann allerdings eine Nachricht hinterlassen "HAllo".

Die Indy Funktion bleibt allerdings so lange in ihrer Routine drin, bis sie die 100 Zeichen erhalten hat, was sie allerdings nie haben wird.

Gibt es daher eine andere Methode mein Problem zu lösen?

Also an alle Delphi/C++ Programmierer mit Indy Erfahrung. Immer her mit euren Vorschlägen

Gruß Tobi


chrisw - Fr 26.08.05 09:07

Wie wäre es mit :

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var tempString,Ersten32Bit,Zweiten32Bit,Rest : String;

tempString := AThread.connection.AllData;
Ersten32Bit := copy(tempString,1,32);
delete(tempstring,1,32);
Zweiten32Bit := copy(tempString,1,32);
delete(tempstring,1,32);
Rest := tempString;


Grendel - Fr 26.08.05 09:22

Da das PHP-Script beim verschicken die genaue Länge der Daten kennt würde ich, ähnlich wie z.B. HTTP, einfach einen Header mit der zu erwartenden Länge vor die Daten hängen und der Empfänger kann den Empfangspuffer aufs Byte genau reservieren.

Bis neulich ...


ttobsen - Fr 26.08.05 12:34

user profile iconGrendel hat folgendes geschrieben:
Da das PHP-Script beim verschicken die genaue Länge der Daten kennt würde ich, ähnlich wie z.B. HTTP, einfach einen Header mit der zu erwartenden Länge vor die Daten hängen und der Empfänger kann den Empfangspuffer aufs Byte genau reservieren.

Bis neulich ...


Ganu das wollt ich aber verhindern aufgrund das ein User die Daten patchen könnte und somit den Server zum Absturz bringt.

Mein Text oben:

Zitat:
Doch da gibt es das Problem das man ohne Probleme die Daten patchen kann und somit den Server aufhängen kann. Ein User könnte zum Beispiel im Z Block schreiben: 100, dann allerdings eine Nachricht hinterlassen "HAllo".

Die Indy Funktion bleibt allerdings so lange in ihrer Routine drin, bis sie die 100 Zeichen erhalten hat, was sie allerdings nie haben wird.


@chrisw:

Hab das gerade ausprobiert. Es funktioniert, aber so langsam, das php nichtmehr wartet bis die antwort vom server kommt. So wie es ausschaut bleibt mir also doch nur die Lösung das vorherige versenden der Datenlänge, oder?

Gruß Tobi


Grendel - Fr 26.08.05 12:39

user profile iconttobsen hat folgendes geschrieben:

Ganu das wollt ich aber verhindern aufgrund das ein User die Daten patchen könnte und somit den Server zum Absturz bringt.

Mein Text oben:

Zitat:
Doch da gibt es das Problem das man ohne Probleme die Daten patchen kann und somit den Server aufhängen kann. Ein User könnte zum Beispiel im Z Block schreiben: 100, dann allerdings eine Nachricht hinterlassen "HAllo".

Die Indy Funktion bleibt allerdings so lange in ihrer Routine drin, bis sie die 100 Zeichen erhalten hat, was sie allerdings nie haben wird.

Verstehe ich nicht. Was ist ein "Z Block" und wieso soll der User Einfluss auf die Größe haben?
Wenn Das PHP-Script die kompletten Daten zusammengebaut hat, also direkt vor dem Senden, ist die Länge doch fest und nichtmehr änderbar. Wo soll der User da nochwas manipulieren können?

Bis neulich ...


ttobsen - Fr 26.08.05 13:08

Weil der User schließlich das PHP Script erhält und in diesem dann rumpfuschen kann. Ausserdem ist diese Shcnittstelle zu meinem Server frei für sämtlichen andere Leute und jeder kann somit die Daten Patchen.

Aber ich habe gerade was anderes entdeckt:

Wenn ich AThread.Connection.Readln();

Mache kann ich noch den PArameter angeben, bei welchen Zeichen/String die eingabe zuende ist. Dort setzt ich dann einfach nenn MD5 Hash ein, kombiniert aus Username und Passwort.

Gruß Tobi