さて、長くなります!
私が取り組んでいるLANシミュレーションプロトコルのために、ドロップされたUDPパケットを管理するための再送信スキームを作成しました。
パケット ストレージ
TDataBuffer = record
PacketID : WORD;
Packet : TMemoryStream;
end;
PDataBuffer = ^TDataBuffer;
関連する DataModule クラス メンバー
fRxDataPacketList : TThreadList20;
fTxDataPacketList : TThreadList20;
procedure CreateDataBuffer
(PacketID : WORD; Packet : TMemoryStream;
var DataBuffer : PDataBuffer);
procedure DestroyDataBuffer
(var DataBuffer : PDataBuffer);
procedure AddPacketToPacketList
(PacketID : WORD; Packet : TMemoryStream;
RecievedPacket : Boolean);
function GetPacketFromTxDataPacketList
(PacketID : WORD; var Packet : TMemoryStream): Boolean;
TThreadList20: これは、スレッド フレンドリーで、暗号化と圧縮をサポートする TList のラッパー クラスです。
私の質問に関係のないRx側を処理するための別の手順があるので、スキップします。
創造
procedure TDataModuleClient.CreateDataBuffer
(PacketID : WORD; Packet : TMemoryStream;
var DataBuffer : PDataBuffer);
begin
New (DataBuffer);
DataBuffer.PacketID := PacketID;
DataBuffer.Packet := TMemoryStream.Create;
if Assigned (Packet) then
begin
DataBuffer.Packet.CopyFrom (Packet,Packet.Size); // NO AV HERE
DataBuffer.Packet.Position := 0;
end;
end;
破壊
procedure TDataModuleClient.DestroyDataBuffer
(var DataBuffer : PDataBuffer);
begin
DataBuffer.Packet.Free;
Dispose (DataBuffer);
end;
リストへの追加
procedure TDataModuleClient.AddPacketToDataPacketList
(PacketID : WORD; Packet : TMemoryStream; RecievedPacket : Boolean);
var
DataBuffer : PDataBuffer;
begin
CreateDataBuffer (PacketID,Packet,DataBuffer);
if RecievedPacket then
fRxDataPacketList.Add (TObject (DataBuffer))
else
begin
fTxDataPacketList.Lock;
try
fTxDataPacketList.Add (TObject (DataBuffer));
if fRxDataPacketList.Count = 21 then
begin
DataBuffer := PDataBuffer (fTxDataPacketList [0]);
DestroyDataBuffer (DataBuffer);
fTxDataPacketList.Delete (0);
end;
finally fTxDataPacketList.Unlock;
end;
end;
end;
リストからの抽出
function TDataModuleClient.GetPacketFromTxDataPacketList
(PacketID : WORD; var Packet : TMemoryStream): Boolean;
var
DataBuffer : PDataBuffer;
I : Integer;
begin
Result := False;
fTxDataPacketList.Lock;
try
for I := fTxDataPacketList.Count - 1 downto 0 do
begin
DataBuffer := PDataBuffer (fTxDataPacketList [I]);
if DataBuffer.PacketID < PacketID then
begin
DestroyDataBuffer (DataBuffer);
fTxDataPacketList.Delete (I);
end
else if DataBuffer.PacketID = PacketID then
begin
Result := True;
Packet := TMemoryStream.Create;
Packet.CopyFrom
(DataBuffer.Packet,DataBuffer.Packet.Size); // AV HERE
Packet.Position := 0;
DestroyDataBuffer (DataBuffer);
fTxDataPacketList.Delete (I);
break;
end;
end;
finally fTxDataPacketList.Unlock;
end;
end;
パケット: 出力変数。
助けてください。コードの量のおかげで、何かを推測するのは難しいように見えます。