AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TCP Filelistening

Ein Thema von Briand · begonnen am 14. Jan 2014 · letzter Beitrag vom 1. Mär 2014
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#11

AW: TCP Filelistening

  Alt 24. Jan 2014, 16:36
Immernoch fehlerhaft!
Das ursprngliche Problem, wo ich eine Lösung dafür in meinem zweiten Beitrag beschrieben habe, ist ungelöst..

Edit1: Kann sein, dass ReceiveText() und SendText() das per LineBreak Marker doch regelt.. In dem Fall sollte es passen; muss halt nur einer bestätigen bzw. nachkucken.

Edit2: Ich hab schnell nachgekuckt:
Delphi-Quellcode:
function TCustomWinSocket.ReceiveText: AnsiString;
begin
  SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));
  SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result)));
end;

function TCustomWinSocket.SendText(const s: AnsiString): Integer;
begin
  Result := SendBuf(Pointer(S)^, Length(S) * SizeOf(AnsiChar));
end;
Folglich kannste mein Edit1 vergessen --> dein Problem ist weiterhin nicht gelöst! Der Fehler wird nur selten auftreten (bei hoher RTT und niedriger Window/Buffersize)
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (24. Jan 2014 um 16:41 Uhr)
  Mit Zitat antworten Zitat
Briand
(Gast)

n/a Beiträge
 
#12

AW: TCP Filelistening

  Alt 27. Jan 2014, 00:07
Also Aphton ich verstehe da leider nur Bahnhof.....Bin halt ein Neuling in dem Bereich.

Wie müsste mann dann das machen damit es richtig funktionier?
  Mit Zitat antworten Zitat
Briand
(Gast)

n/a Beiträge
 
#13

AW: TCP Filelistening

  Alt 10. Feb 2014, 22:35
hmmmm bin nach fast 2 Wochen leider immer noch nicht weiter....
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#14

AW: TCP Filelistening

  Alt 10. Feb 2014, 23:27
Wie bereits erwähnt, wenn du 10 Bytes/Zeichen schicken willst, wird nicht garantiert, dass auch alle 10 geschickt werden...
Die Sendefunktion liefert dir nen Integer zurück, der dir die tatsächliche Anzahl an geschickten Bytes sagt.

Wenn du es lokal testest, wirst du auf das Problem nicht stoßen, da eben der Ping einfach zu gering ist.

Beispiel, wie so eine Kommunikation aussehen könnte, wenn man zwei Nachrichten "abCDef" und "Hallo" schicken würde:
Code:
Sende: "abCDef"
Sende liefert zurück 2 - dh. "ab" wurde geschickt, daher -->

Sende: "CDef"
Sende liefert zurück 0 - konnte nichts schicken; warum auch immer -->

Sende: "CDef"
Sende liefert zurück 4 -> passt

Sende: "Hallo"
Sender liefert zurück 5 -> passt

####

Empfange 1000 Zeichen:
Empfange liefert 0 zurück

Empfange 1000 Zeichen:
Empfange liefert 3 zurück -> "abC"

Empfange 1000 Zeichen:
Empfange liefert 1 zurück -> "D"

Empfange 1000 Zeichen:
Empfange liefert 5 zurück -> "efHal"

Empfange 1000 Zeichen:
Empfange liefert 2 zurück -> "lo"
Bei diesem Verhalten kannst du nun folgende Rückschlüsse ziehen:
- Du bist dafür zuständig, dass du deine Daten wirklich vollständig überträgst
- Beim Empfangen musst du auch Pakete unterscheiden können

Das Problem kann man - wenn man es ordentlich machen will - ganz elegant über Streams lösen:
Pro Socket ein Sende & Empfangstream instanzieren.

Alles was geschickt werden soll, wird in ein Paket gekapselt:
Ein Paket besteht aus [Größe][Daten]

Zum Schicken schreibt man die Pakete hinten im Sendestream rein.
Der Sendestream wird periodisch abgearbeitet und wie beim Beispiel oben wird der Komplette Inhalt des Streams versucht zu versenden und versendete Bytes werden verworfen!

Beim Empfangen puffert man auch alles in den Empfangsstream hinten rein. Der Empfangsstream muss auch perodisch abgerabeitet werden und es muss nach folgendes geprüft werden:
- habe ich GrößeInBytes(Paket.[Größe]) empfangen?
- falls ja, habe ich GrößeInBytes(Paket.[Größe]) + Paket.[Größe] empfangen?
- falls ja, dann erhält der Empfangsstream mindestens ein vollständiges Paket, das rausgenommen werden kann

Beispiel (hier gehen wir mal davon aus, dass die [Größe] 1 Byte groß ist):
Code:
SendePuffer.send("abCDef")
-> SendePuffer erhält folgenden Datenstrom [6]["abCDef"]

SendePuffer.send("Hallo")
-> SendePuffer erhält folgenden Datenstrom [5]["Hallo"]

Sendepuffer sieht so aus:
[6]["abCDef"][5]["Hallo"]

Periodisches abarbeiten des Sendepuffers:
Sende.. liefert zurück: 2 -->
["bCDef"][5]["Hallo"]

Sende... liefert zurück: 8 -->
["llo"]

Semde... liefert zurück: 3 -->
Leer

####

Empfange.. liefert zurück: 3 -->
Empfangspuffer:
[6]["ab"]

Paket entnehmbar?:
- ist die Größe des Empfangspuffers (3) > GrößeInBytes(Paket.[Größe]) (1) --> ja
- ist GrößeInBytes(Paket.[Größe]) (1) + Paket.[Größe] (=[6] = 6) <= Größe des Empfangspuffer?
also ist 1+6 <= 3 --> nein --> folglich kann man kein Paket rausfischen

Empfange.. liefert zurück: 10 -->
Empfangspuffer:
[6]["abCDef"][5]["Hallo"]

Paket entnehmbar?:
- 13 > 1 --> ja
- 1 + 6 <= 13 --> ja
- dh. 1 + 6 Bytes können aus dem Empfangspuffer entnommen werden
Paket: [6]["abCDef"]
Empfangspuffer:
[5]["Hallo"]

Paket entnehmbar?:
- 6 > 1 --> ja
- 1 + 5 <= 6 --> ja
- dh. 1 + 5 Bytes können aus dem Empfangspuffer entnommen werden
Paket: [5]["Hallo"]
Empfangspuffer:
Leer
[5]["Hallo"]
Alles was du nun zu tun hast, ist genau das hier umzusetzen.
Mehr nicht.

Achja, kann durchaus sein, dass es irgendwelche fertige Bibliotheken gibt, die das hier bereits für dich tun.. Da müsstest du dich erkundigen; aber an sich ist das eig. in 20 Minuten programmiert. Sollte ne Fingerübung sein.

Die Beschreibung könnte an manchen Stellen unverständlich sein; hab nicht drüber gelesen.. Sollte aber trotzdem helfen!
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Briand
(Gast)

n/a Beiträge
 
#15

AW: TCP Filelistening

  Alt 10. Feb 2014, 23:34
Danke Dir werd mich morgen mal damit beschäfftigen und mich ev. nochmals melden.

L.g Briand
  Mit Zitat antworten Zitat
Briand
(Gast)

n/a Beiträge
 
#16

AW: TCP Filelistening

  Alt 1. Mär 2014, 15:54
So hab das Problem gelöst.

Es war so das das Socket Receive Event mehrmals aufgerufen wurde und ich immer nur den Schluss des Strings bekam.
Beim SendText schicke ich die grösse des Strings mit damit ich beim empfangen weiss wieviel das kommen sollte.

Habe das jetzt so gelöst.

Delphi-Quellcode:
procedure TForm1.ServerSocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
var Befehl : String;
begin

Datas := Datas + socket.ReceiveText;

if Copy(datas, 1, 1) = '*then
begin
Delete(datas,1,pos('*',datas));
buffer := strtoint(copy(datas,0,pos('*',datas)-1));
Delete(datas,1,pos('*',datas));
end;

if length(datas) >= buffer then
begin
Befehl := copy(datas,0,pos('|',datas)-1);

if Befehl = ('DRIVES') then
begin
Delete(Datas,1,pos('|',Datas));
TeileDrives(datas);
buffer := 0; datas := '';
end;

if Befehl = ('FOLDERS') then
begin
Delete(Datas,1,pos('|',Datas));
TeileFolders(datas);
buffer := 0; datas := '';
end;

if Befehl = ('FILES') then
begin
Delete(Datas,1,pos('|',Datas));
TeileFiles(datas);
buffer := 0; datas := '';
end;

Geändert von Briand ( 1. Mär 2014 um 15:57 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.157 Beiträge
 
Delphi 12 Athens
 
#17

AW: TCP Filelistening

  Alt 1. Mär 2014, 16:37
Kleine Datenhäppchen werden gern mal zusammengefasst
und große Blöcke werden natürlich aufgeteilt, denn viele Übertragungsprotokolle haben eine "maximale" Größe, wieviele Daten in ein Datenpacket reinpassen.

Außerdem können/müssen natürlich nicht alle Datenpackete gleichzeitig am Ziel ankommen.

Und nun rate mal, was das für deine empfangenen Datenhäppchen bedeutet.
In ReciveText muß also noch nicht alles drin sein.
Irgendwie sieht man auch nicht wo/ob buffer ausgewertet wird.
Und das Löschen von datas kann den nächsten Befehl (teilweise) löschen.

[edit] Hab das length(datas) >= buffer übersehn, aber auch dir scheint wohl aufgefallen zu sein, daß length(datas) = buffer wohl nicht immer funktioniert.

Zitat:
Delphi-Quellcode:
Delete(Datas,1,pos('|',Datas));
...
buffer := 0; datas := '';
Das sieht nach nutzlos doppeltem Code aus.

PS: Die 0 in dem Copy sieht nicht grade richtig aus.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 1. Mär 2014 um 16:45 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#18

AW: TCP Filelistening

  Alt 1. Mär 2014, 17:22
Jo, das sieht schonmal logisch korrekter aus

Aber ein kleiner Fehler ist immernoch drinnen
Zitat:
Delphi-Quellcode:
if Copy(datas, 1, 1) = '*then
begin
Delete(datas,1,pos('*',datas));
buffer := strtoint(copy(datas,0,pos('*',datas)-1));
Delete(datas,1,pos('*',datas));
end;
Du gehst davon aus, dass, wenn ein '*' am Anfang von "datas" (dein Buffer) steht, dann ist der Rest (die Längenangabe mit Trenner '*') auch drinnen, also z.B. so~
'*20*' (für Länge = 20)

WAS ist aber, wenn z.B. ReceiveText nur 2 Zeichen zurückliefert; also macht ein
Datas := Datas + ReceiveText folgendes z.B.:
Code:
Datas = ''
ReceiveText = '*2'
Datas = '*2'
Die If Beindung passt hier, da das erste Zeichen ein '*' ist - ach übrigens, Strings können per Klammer ab 1 indiziert werden, verwende dafür einzelne Zeichen kein Copy bitte also so in etwa:
Delphi-Quellcode:
if Datas[1] = '*then
  //...
[Edit]
Die If Bedingung so umändern:
Delphi-Quellcode:
// Verbesserungsvorschlag
if (Datas[1] = '*') and (Pos('*', Copy(Datas, 2, Length(Datas))) <> 0) then
An erster Stelle muss ein '*' stehen und irgendwo danach (= ohne erstes Zeichen -- das ist das, was Copy zurückliefert) muss ein '*' vorkommen
[/Edit]

Abschließend möcht ich nochmals erwähen - das Senden muss nach dem selben Prinzip erfolgen.. Lege dort auch ein Datas an, schreibe ne neue Procedure zum Schicken von Daten, welches am Ende von Datas deinen String mit Längenangabe dazu "tut"..
Datas muss dann, wie zuvor beschrieben, (wenn nötig, häppchenweise) periodisch übertragen werden, sofern nicht leer!
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton ( 1. Mär 2014 um 17:30 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:11 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz