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;