Registriert seit: 3. Sep 2004
4.629 Beiträge
Delphi 10.2 Tokyo Starter
|
AW: Socket C&S
7. Feb 2018, 00:00
Dieses Beispiel solltest du 1 zu 1 auf Sockets übertragen können:
Delphi-Quellcode:
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;
Hier noch zwei Testvektoren:
Delphi-Quellcode:
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
Ich verwende hier absichtlich das extra Feld FBufferLen
statt direkt FBuffer.Size
, um frequente Speicher-Allocs zu vermeiden.
|
|
Zitat
|