![]() |
Socket C&S
Hallo,
ich schicke mit
Code:
Daten an den Client. Dort kommen die Daten
SendBuf(buf[0], Length(buf));
Code:
aber nicht in einem Stück an. Wie groß darf buf max. sein? Oder kann erzwingen das alles komlett empfangen werden kann?
Socket.ReceiveBuf(buf[0], Socket.ReceiveLength);
Danke und beste Grüße |
AW: Socket C&S
Zitat:
Du musst dir ein eigenes kleines Protokoll bauen. Einfachste Lösung wäre das Vorwegsenden eines Ints/Int64 mit der Länge der Daten. Edit: Auf Empfängerseite sind leider einige Dinge zu beachten. Z.b. kann es nicht nur passieren, dass die Pakete fragmentiert werden, sondern mehrere Pakete können auch "in einem Rutsch" ankommen. Auch kann es dir passieren, dass dein Int/Int64 nicht vollständig ist. Du benötigst also auf jeden Fall einen Zwischenspeicher (sowas wie eine Queue [FIFO] für zusammenhängende Daten) und musst Diesen dann in einer Schleife stückweise abarbeiten. |
AW: Socket C&S
MTU von Ethernet ist normalweise 1518 minus
Indy macht aber auch manchmal Blödsinn. Ich habe auch schon mal das Problem gehabt, dass bestimmte Indy-Methoden das erste Byte einzeln geschickt haben. |
AW: Socket C&S
Hallo,
wenn die Daten blockweise eintreffen sollte ReceiveLength die jeweilige Blockgröße angeben. Wie ich aber lese ist der Wert von ReceiveLength nicht immer genau. Damit wird es unmöglich die gesamten Daten "zusammenzupacken". Oder hat jemand doch ein Stück Quelltext? Beste Grüße |
AW: Socket C&S
Irgendwie so (nicht getestet):
Delphi-Quellcode:
var
buf: TBytes; len: Integer; begin // bla bla len := Length(buf); SendBuf(len, 4); SendBuf(buf[0], Length(buf)); end;
Delphi-Quellcode:
var
buf: TBytes; len: Integer; begin Socket.ReceiveBuf(len, 4); SetLength(buf, len); Socket.ReceiveBuf(buf[0], len); // bla bla end; |
AW: Socket C&S
Delphi-Quellcode:
enthält die Größe der ankommenden Daten. Aber wie du schon korrekt erkannt hast, wird ein
ReceiveLength
Delphi-Quellcode:
manchmal in mehrere
Send
Delphi-Quellcode:
s aufgeteilt sozusagen. Die Summe aller
Recv
Delphi-Quellcode:
s entspricht dann der bei
ReceiveLength
Delphi-Quellcode:
angegebenen Gesamtgröße.
Send
Der Trick ist, dass du die Größe manuell einmal mitschickst, wie ich oben schon beschrieben habe. Zitat:
|
AW: Socket C&S
Dieses Beispiel solltest du 1 zu 1 auf Sockets übertragen können:
Delphi-Quellcode:
Hier noch zwei Testvektoren:
type
TForm1 = class(TForm) ... strict private FBuffer: TMemoryStream; FBufferLen: UInt32; ... procedure TForm1.Recv(const Data: TBytes); type PUInt32 = ^UInt32; var N: UInt32; S: String; begin // Erstmal alle Daten in den Buffer schreiben FBuffer.Write(Data, Length(Data)); Inc(FBufferLen, Length(Data)); // Pakete parsen while (FBufferLen >= SizeOf(N)) do begin N := PUInt32(FBuffer.Memory)^; if (FBufferLen < SizeOf(N) + N) then begin Break; end; // Mindestens ein Paket vollständig angekommen SetLength(S, N div SizeOf(Char)); CopyMemory(@S[1], PByte(FBuffer.Memory) + SizeOf(N), N); ShowMessage(S); // Jetzt muss das bearbeitete Paket aus dem Buffer "entfernt" werden CopyMemory(FBuffer.Memory, PByte(FBuffer.Memory) + SizeOf(N) + N, FBufferLen - SizeOf(N) - N); Dec(FBufferLen, SizeOf(N) + N); FBuffer.Position := FBuffer.Position - SizeOf(N) - N; end; end;
Delphi-Quellcode:
Ich verwende hier absichtlich das extra Feld
procedure TForm1.TestFragmented;
const S = 'Dieser String wird mehreren Paketen gesendet'; X = 40; var N: UInt32; D, F1, F2: TBytes; begin N := Length(S) * SizeOf(Char); SetLength(D, SizeOf(N) + N); Move(N, D[0], SizeOf(N)); Move(S[1], D[SizeOf(N)], N); SetLength(F1, X); Move(D[0], F1[0], X); SetLength(F2, Length(D) - X); Move(D[X], F2[0], Length(D) - X); // Einzelnes Paket wird fragmentiert empfangen Recv(F1); Recv(F2); end; procedure TForm1.TestMultiple; const S1 = 'Dies ist String 1'; S2 = 'Dies ist String 2'; var N1, N2: UInt32; D: TBytes; begin N1 := Length(S1) * SizeOf(Char); N2 := Length(S2) * SizeOf(Char); SetLength(D, SizeOf(N1) + N1 + SizeOf(N2) + N2); Move(N1, D[0], SizeOf(N1)); Move(S1[1], D[SizeOf(N1)], N1); Move(N2, D[SizeOf(N1) + N1], SizeOf(N2)); Move(S2[1], D[SizeOf(N1) + N1 + SizeOf(N2)], N2); // Zwei Pakete werden als einzelnes Paket empfangen Recv(D); end
Delphi-Quellcode:
statt direkt
FBufferLen
Delphi-Quellcode:
, um frequente Speicher-Allocs zu vermeiden.
FBuffer.Size
|
AW: Socket C&S
Puffer zusammenpacken ist an sich kein Problem. Nur der Bezug zum Socket war mir wichtig.
Es sieht so aus, als wäre die max. Größe eines Blocks ein High(Word). Ich werde versuchen schon beim Versenden diese max. Blockgröße nicht zu überscheiten. |
AW: Socket C&S
Vielleicht hilft Dir der Thread noch etwas weiter:
![]() |
AW: Socket C&S
Zitat:
Die 65k bzw. mitlerweile meisten 256k, von denen man öfters mal liest, beziehen sich auf die Größe des internen Empfangs-Buffers unter Windows und nicht auf die MTU. Die EINZIGE zuverlässige Methode bei TCP ist eine eigene Pakettrennung. Denn selbst, wenn du es schaffen würdest dich immer korrekt an der MTU zu orientieren, dann schützt dich das weiterhin nicht davor, dass mehrere kleine Pakete zu einem großen Datenblock auf Empfängerseite zusammengefügt werden. Mein Beispiel verwendet zwar keine Sockets, simuliert aber beide der primären Situationen, die beim Versand von Daten per TCP Socket auftreten und ist demnach absolut das, was du haben möchtest. Die
Delphi-Quellcode:
Methode kannst du praktisch 1 zu 1 übernehmen und mit den Daten des Sockets füllen und beim
Recv
Delphi-Quellcode:
schickst du halt schnell einen
Send
Delphi-Quellcode:
mit der Gesamtdatenmenge des Pakets vorweg. Ist kein großer Aufwand.
UInt32
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz