Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: Ist der Server zu "schnell"?

  Alt 29. Mär 2011, 06:37
Wie ich bereits erwähnte, wird OnClientRead aufgerufen, wenn Daten da sind. Das heißt aber nicht, dass das erst passiert, wenn ALLE Daten da sind. So ein Socket ist wie ein Schlauch, durch den Kugeln rollen. Du kippst vorne welche rein und irgendwann trudeln die hinten wieder raus. Aber ob die am Stück herauskommen, oder peu-a-peu, das weiss man nicht. Das einzige, worauf Du dich (eigentlich) verlassen kannst, ist die Reihenfolge der Kugeln und das alle ankommen (meistens). Wenn aber jemand den Schlauch durchschneidet, haste Pech.

Du musst Dir selbst Gedanken machen, wie Du sicherstellst, das alle Daten angekommen sind. Dazu kannst Du auf die erste Kugel schreiben, wie viele denn nun kommen. Oder Du färbst die letzte Kugel ROT. Dann dürfen aber in den Nachrichten keine rote Kugeln vorkommen. Oder Du überklebst rote Kugeln mit einem großen Schild: "ROTE Kugel" und färbst die im Client wieder ein, nachdem die ENDE-Kugel (die ja auch rot ist) angekommen ist.

Egal wie, Du musst die Daten also erst einmal sammeln.

So zum Beispiel (Pseudocode, aber vielleicht verständlich):
Delphi-Quellcode:
...
MyBuffer.AddBytes (BytesFromSocket);
While True Do
  If TotalLength = 0 then
    If MyBuffer.Count >= 4 then begin // 4-Byte Längeninfo ist angekommen
      TotalLength := MyBuffer.FirstFourBytesAsInteger; // Die 4 Bytes als Integer interpretieren
      MyBuffer.RemoveBytes (4); // und dann vorne wegschnippeln
    end else
      break // Die Längeninformation ist noch nicht vollständig
  else
    If MyBuffer.Count >= TotalLength then begin // Alle Bytes sind angekommen
// (es könnte aber auch schon ein Teil des nächsten Blocks dabei sein)
      Data := MyBuffer.ExtractBytes (TotalLength); // Datenblock extrahieren
      MyBuffer.RemoveBytes(TotalLength); // wegschnippeln
      ProcessData (Data); // verarbeiten (sollte schnell gehen)
      TotalLength := 0; // und auf den nächsten Block warten
  End else
    break; // Die Dateninformation ist noch nicht vollständig
Die Schleife dient dazu, sofort alle vollständig empfangenen Blöcke zu verarbeiten.

Alternativ kannst Du auch mit einem speziellen Endezeichen (rote Kugel) arbeiten:
Delphi-Quellcode:
...
MyBuffer.Add (BytesFromSocket);
EndPos := MyBuffer.PositionOf (EndOfDataMarker);
While EndPos >= 0 Do Begin
  Data := MyBuffer.ExtractBytes (EndPos); // Datenblock extrahieren
  MyBuffer.RemoveBytes(EndPos+1); // Datenblock + Endmarker wegschnippeln
  ProcessData (Data); // verarbeiten (sollte schnell gehen)
  EndPos := MyBuffer.PositionOf (EndOfDataMarker);
End;
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat