Einzelnen Beitrag anzeigen

Unity

Registriert seit: 26. Sep 2008
2 Beiträge
 
#1

Server mit Liste aus Records crasht

  Alt 26. Sep 2008, 00:45
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
  Mit Zitat antworten Zitat