Hey!
Ich hab ein kleines Problemchen mit einem Serverprogramm.
Clients melden sich per Handshake bei meinem Server an. Ich speichere diese dann in einer Liste mittels Record.
In einem zweiten Thread sende ich alle 20 Sekunden eine Anfrage an alle Clients die in dieser Liste stehen.
Ist der Client noch "aktiv" sendet er eine Antwort welche dann im Haupthread empfangen wird und den Timestamp des letzten Kontakts aktualisiert (mittels for Schleife durch die Liste).
Ist der letzte Kontaxt länger als X Sekunden her, wird der Client aus der Liste gelöscht. Er wird ebenfalls gelöscht, sollte er eine bestimmte Nachricht senden.
Das Problem ist nun, dass der Server ohne irgendwelche Anzeichen einfach crasht.
Ich habe bereits versucht den Fehler durch debug Meldeungen und neuschreiben zu finden. Leider ohne Erfolg.
Ich gehe davon aus, dass der Fehler an der Liste bzw. den Records liegt.
Der Fehler tritt sporadisch auf, ein Muster ist nicht zu erkennen.
Hier nun der Code zu den beschrieben Abläufen:
Delphi-Quellcode:
function TMain.GetUnixTime: int64;
var
st:_SYSTEMTIME;
ft:_FILETIME;
begin
// first get windows SYSTEMTIME in UTC / GMT
GetSystemTime(st);
// now convert to windows FILETIME
SystemTimeToFileTime(st, ft);
// now to UNIXTIME
result := round((int64(ft) - int64(116444736000000000)) / 10000000);
end;
{ ... }
type
TStrArray = array of string;
PRecord = ^TRecord;
TRecord = record
name: string;
Desc: string;
Version: string;
ID: Integer;
ComIP: String;
ComPort: Integer;
Timestamp: int64;
end;
{ ... }
private
List: TList;
Rec: PRecord;
{ ... }
procedure TMain.CreateList;
begin
List:=TList.Create;
end;
{ ... }
{ Speichern der Clients: }
New(Rec);
Rec.Version := sVersion;
Rec.name := sName;
Rec.ServerComIP := ABinding.PeerIP;
Rec.ServerComPort := ABinding.PeerPort;
Rec.Timestamp := GetUnixTime();
List.Add(Rec);
{ Thread zum senden der Anfrage: }
function Thread(p: Pointer): Integer;
var i: Integer;
begin
while (1=1) do begin
if Main.List.Count >= 1 then begin
for i:=0 to (Main.List.Count-1) do begin
if ((Main.GetUnixTime() - TRecord(Main.List[i]^).Timestamp) > 50) then begin
Dispose(PRecord(Main.List[i]));
Main.List.Delete(i);
end
else begin
if (Main.isCreated) then begin
Main.UdpServer.Send(TRecord(Main.List[i]^).ComIP, TRecord(Main.List[i]^).ComPort, #$2f#$00#$03#$08);
end
end
end;
end;
Sleep(20000);
end;
result:=0;
end;
{ Aktualisierung des Timestamps: }
for i:=0 to List.Count-1 do begin
if ((TRecord(List[i]^).ComIP = ABinding.PeerIP) and (TRecord(List[i]^).ComPort = ABinding.PeerPort)) then begin
TRecord(List[i]^).Timestamp := GetUnixTime();
break;
end;
end;
{ Löschen bei Abmeldung: }
for i:=0 to List.Count-1 do begin
if ((TRecord(List[i]^).ComIP = ABinding.PeerIP) and (TRecord(List[i]^).ComPort = ABinding.PeerPort)) then begin
Dispose(PRecord(Main.List[i]));
List.Delete(i);
break;
end;
end;
Meine Vermutung war, dass beim Löschen aus der Liste etwas schief geht. Ich habe es darauf hin mit und ohne Dispose versucht... hat aber nichts gebracht.
Über Ideen würde ich mich freuen
Grüße,
Unity