Autor |
Beitrag |
7h3_L!z4rD
Hält's aus hier
Beiträge: 5
WinXPPro
D7
|
Verfasst: So 28.02.10 20:55
Momentan bin ich dabei ein Programm zu programmieren, welches als eine Unterfunktion die Aufgabe hat, aus einem Array, in dem Server-IPs gespeichert sind den schnellsten zu ermitteln. Ich bin jedoch momentan total ratlos wie ich das in Delphi 7 umsetzen könnte. Ich weiß, dass es ein FTP-Client-Event gibt, welches Aktionen ausführen kann, wenn der Download fertig gestellt ist,... OnAfterGet
Naja im großen und ganzen würde ich gern eine
"function fastestIP(const ServerArray: Array of shortstring; const aktuellerServerINDEX:byte; var fertig:boolean):shortstring" erschaffen,
die nun nacheinander von jedem Server aus dem ServerArray eine Testdatei herunterläd und nachdem das geschehen ist, die gebrauchte Zeit in ein zeit-Array eintägt, mit dem aktuellen ServerIndex und wenn alle Server durchgegangen sind soll der schnellste Server ausgegeben werden, wenn der Download aber länger als 10 Sekunden dauert soll abgebrochen werden und mit dem nächsten fortgefahren werden...(bspw wenn der Server nicht erreichbar ist oder zu langsam) Die Testdatei ist etwa 7MB groß und das ganze soll über 100/1000er LAN gehen...
momentan ist das alles ziemlich die Baustelle schlechthin, aber bisher hab ich folgendes:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| function fastestIP(const ServerArray:array of shortstring; const aktuellerServerINDEX:byte; const fertig:boolean; var fertigout:boolean):shortstring; begin if (Length(ServerArray) = 1) then begin Result := ServerArray[0]; fertigout := true; end else begin FormHauptprogramm.IdFTPFast.Port := 21; FormHauptprogramm.IdFTPFast.Username := 'anonymous'; FormHauptprogramm.IdFTPFast.Password := ''; FormHauptprogramm.IdFTPFast.Host := ServerArray[aktuellerServerINDEX]; FormHauptprogramm.IdFTPFast.Connect(true,-1); queryperformancecounter(zeit[aktuellerServerINDEX]); FormHauptprogramm.IdFTPFast.Get('\SPEEDTEST.TXT',programmverzeichnis+'\speedtest.txt',true,false); end; end;
procedure TFormHauptprogramm.IdFTPFastAfterGet(ASender: TObject; VStream: TStream); var neuezeit:int64; begin queryperformancecounter(neuezeit); Zeit[aktuellerServerINDEX] := neuezeit - Zeit[aktuellerServerINDEX]; aktuellerServerINDEX := aktuellerServerINDEX + 1; if aktuellerServerINDEX > Length(ServerArray) then fertig := true; IdFTPFast.Quit; end; |
und in der Prozedur, die die funktion aufruft steht momentan folgendes:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| schnellsterServer := 'ERROR!'; schnellsterServer := fastestIP(ServerArray,aktuellerServerINDEX,fertig,fertigout); time_for_timeout := 0; timeout := false; repeat TimerFTP.Enabled := true; until (fertigout or timeout); |
(die repeat until Schleife ist nur dafür da, dass das Programm solange wartet, bis "schnellsterServer" einen Wert hat)
und der Timer sieht wie folgt aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TFormHauptprogramm.TimerFTPTimer(Sender: TObject); begin inc(time_for_timeout); if time_for_timeout = 10 then begin TimerFTP.Enabled := false; timeout := true; end; end; |
Würde mich freuen, wenn mir jemand gedanklich weiterhelfen könnte, denn ich komm einfach nicht weiter...
Momentan benutze ich Indy9 und Delphi7 und wenn es geht würde ich die beiden Komponenten auch weiterhin benutzen wollen 
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: So 28.02.10 23:42
Moin!
Also dein Ansatz über die GUI-Kompo ist irgendwie nix, ich würde eine Server-Test-Thread-Klasse schreiben, der gibste den Hostnamen/IP und die liefert die Verfügbarkeit. Dann kannste auch gleich mehrere auf einmal testen, geht wesentlich schneller.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Xentar
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: Mo 01.03.10 00:14
_________________ PROGRAMMER: A device for converting coffee into software.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 01.03.10 00:24
Moin!
Xentar hat folgendes geschrieben : | Hm, es geht hier nicht um die Verfügbarkeit, sondern Geschwindigkeit. Und da wäre es unvorteilhaft, mehrere gleichzeitig zu testen  |
Die Geschwindigkeit ist doch eine qualitative Eigenschaft der Verfügbarkeit, oder?  Insofern kann ich an meiner Aussage keinen Makel finden.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
7h3_L!z4rD 
Hält's aus hier
Beiträge: 5
WinXPPro
D7
|
Verfasst: Mo 01.03.10 13:08
Japp, es geht vordergründig darum, welcher Server der schnellste ist,...
Aber ich gehe erst einmal davon aus, dass derjenige, der die ServerIPs dem Programm übergibt, selber sicherstellt, dass diese dann auch wirklich vorhanden sind. Es sei denn, die Überprüfung über die Verfügbarkeit lässt sich sehr einfach programmieren. - Immerhin ist das ganze ein Informatik-Projekt für Klasse 12 und mein Wissen über Delphi ist meiner Meinung nach eher begrenzt.
Ich kann euch allerdings einmal kurz das Projekt vorstellen, vielleicht gibt es noch eine viel einfachere Variante, wie man das Problem lösen kann.
Mein Info-Projekt besteht aus zwei Teilprogrammen, einem Server-Programm und einem Client-Programm, das Server-Programm habe ich schon fertig programmiert und funktioniert auch soweit.
Das Server-Programm gibt dem Anwender die Möglichkeit Dateipfade auf FTP-Servern einzugeben, dann natürlich die zugehörigen Dateinamen, wie sie im Client-Programm angezeigt werden sollen und zu guter letzt die Eingabemöglichkeit für die verfügbaren FTP-Server. Sind alle Eingaben getätigt werden nun diese Eingaben im Programmverzeichnis, in dem das Programm ausgeführt wird, in Textdateien abgespeichert. Anschließend wird ein FTP-Server gestartet, der dieses Verzeichnis mit einem Benutzerkonto freigibt. Nebenbei läuft das UDP-Sock-Util gleich zweimal, an dieser Stelle ein Dankeschön an Narses  . Das erste mal als Rückmeldung für den Client (weitere Beschreibung beim Client) und das zweite mal (natürlich andere Ports usw.), für die Überprüfung bei Programmstart, ob schon ein anderer Server aktiv ist. (Quasi sendet der Server ins Netzwerk eine Broadcastanfrage, kommt keine Antwort -Timeout von 5 Sekunden- dann wird die Oberfläche freigegeben, kommt eine Antwort, wird die IP der Antwort angezeigt & der Benutzer aufgefordert eine neue Überprüfung zu starten und die Benutzeroberfläche wird nicht freigegeben, solange es einen weiteren Server im Netzwerk gibt)
Das Clientprogramm schickt eine Broadcastanfrage, auf die der Server nun antwortet. Damit hat der Client die IP vom Server und kann sich nun in den FTP-Server auf dem Server-Programm einloggen und die drei Textdateien (Dateinamen,Dateipfade & ServerIPs) runterladen. Diese werden anschließend in Arrays im Clientprogramm geladen. Die Dateinamen werden in einer Listbox angezeigt, ebenso die ServerIPs (aber die eher informativ). Der Benutzer kann nun die gewünschten Dateien, die er/sie herunterladen will anklicken (Mehrfachauswahl möglich  ) und mit einem Klick auf "Downloaden" werden die angewählten Dateien in ein "Downloadarray" geladen, so und nun kommt mein Problem ins Spiel. Jetzt soll für jede Download-Datei der momentan schnellste Server ermittelt werden und anschließend von dem in das vom Benutzer gewählte Verzeichnis geladen werden. Sind Dateien gepackt, sollen diese auf Benutzerwunsch entpackt werden (nur folgende Formate: 7z, rar, zip - sonst wird es zu komplex). Ist das alles fertig, werden - wieder auf Benutzerwunsch - die gepackten Dateien gelöscht, sofern sie entpackt worden sind. Zu guter letzt soll das Programm den Downloadordner öffnen.
(für das Entpacken habe ich eine SevenZipVCL gefunden, für die FTP-Server/Client benutze ich Indy9, für das Minimieren des ServerProgramms CoolTrayIcon und für alle UDP-Geschichten das UDP-Sock-Util)
Nur euere drei Beiträge bringen mich nicht weiter
- wenn noch irgendetwas unklar ist, kann ich auch die momentanen Programme mit Source hochladen, aber ich glaube eher weniger, dass die was zur Problembehebung beitragen können  -
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 01.03.10 15:24
Moin!
7h3_L!z4rD hat folgendes geschrieben : | Nur euere drei Beiträge bringen mich nicht weiter  |
Tja, ich hatte es befürchtet, ist auch nicht ganz trivial.  Hier also mal ein Ansatz, wie man da ran gehen könnte:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116:
| uses ..., IdFTP;
type TSpeedTestFTP = class(TThread) private FHost: AnsiString; FRef: Integer; FSpeed: Integer; public constructor Create(const AHost: AnsiString; const ARef: Integer; AOnTerminate: TNotifyEvent); procedure Execute; override; property Host: AnsiString read FHost; property Ref: Integer read FRef write FRef; property Speed: Integer read FSpeed; end;
TForm1 = class(TForm) Button1: TButton; ListBox1: TListBox; procedure Button1Click(Sender: TObject); procedure TestFertig(Sender: TObject); end;
var Form1: TForm1; WinTempDir: String;
implementation
constructor TSpeedTestFTP.Create(const AHost: AnsiString; const ARef: Integer; AOnTerminate: TNotifyEvent); begin inherited Create(TRUE); FHost := AHost; FSpeed := -1; FreeOnTerminate := TRUE; OnTerminate := AOnTerminate; Resume; end;
procedure TSpeedTestFTP.Execute; var FTP: TIdFTP; TempFile: String; Speed: Cardinal; begin FTP := TIdFTP.Create(NIL); try try FTP.Host := FHost; FTP.Port := 21; FTP.Username := 'anonymous'; FTP.Password := ''; FTP.Connect; TempFile := WinTempDir +Format('SpeedTest%x',[Random(MaxInt)]); Speed := GetTickCount; FTP.Get('\SPEEDTEST.TXT',TempFile,TRUE); FSpeed := GetTickCount -Speed; except FSpeed := -1; end; try FTP.Disconnect; DeleteFile(TempFile); except end; finally FTP.Free; end; end;
procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin ListBox1.Tag := -1; ListBox1.ItemIndex := -1; for i := 0 to ListBox1.Count-1 do TSpeedTestFTP.Create(ListBox1.Items.Strings[i],i,TestFertig); end;
procedure TForm1.TestFertig(Sender: TObject); begin ListBox1.Items.Objects[TSpeedTestFTP(Sender).Ref] := Pointer(TSpeedTestFTP(Sender).Speed); if (TSpeedTestFTP(Sender).Speed >= 0) then begin if (ListBox1.Tag = -1) or (TSpeedTestFTP(Sender).Speed < ListBox1.Tag) then begin ListBox1.Tag := TSpeedTestFTP(Sender).Speed; ListBox1.ItemIndex := TSpeedTestFTP(Sender).Ref; end; end; end;
initialization Randomize; WinTempDir := IncludeTrailingPathDelimiter(GetEnvironmentVariable('TEMP')); if (WinTempDir = '') then begin SetLength(WinTempDir,MAX_PATH +1); SetLength(WinTempDir,GetTempPath(Length(WinTempDir),PChar(WinTempDir))); end; | Hier wird allerdings kein Abbruch des Downloads gemacht, sondern immer die komplette Datei runtergeladen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
7h3_L!z4rD 
Hält's aus hier
Beiträge: 5
WinXPPro
D7
|
Verfasst: Fr 05.03.10 13:04
Danke erst einmal für deine Bemühungen
Ich werde mich die nächsten Tage mal hinsetzen und das ganze mal durchschauen & hoffentlich auch verstehen, was ja bei Fremdcode meist sone Sache ist...
Melde mich wieder, wenn noch Unklarheiten auftreten oder alles funktionieren sollte.
|
|
7h3_L!z4rD 
Hält's aus hier
Beiträge: 5
WinXPPro
D7
|
Verfasst: Mo 08.03.10 13:57
Soweit alles in Ordnung, hab mir das ganze mal etwas genauer angeschaut & lässt sich auch ohne Fehlermeldung compilieren und starten.
Habe jetzt meine lokale IP (127.0.0.1) in die Listbox eingetragen & einen FTP-Server (Filezilla Server - Anonymous-Benutzer wurde auch angelegt) gestartet.
Mit dem Filezilla Client kann ich auch über den Anonymous-Nutzer auf die Freigabe zugreifen.
Allerdings tut sich auf den Button-Click nichts & der Thread loggt sich auch nicht im Server ein.
Da ich bisher keine Erfahrung mit dem Umgang mit Threads habe, hab ich mir das Thread-Turotial durchgelesen ( Thread-Turotial-PDF) daher kann das auch an einem kleinen Dummheitsfehler meinerseits liegen, den ich gerade nicht entdecke...
(extra thread-unit wurde angelegt, Aufruf dieser in der main unit, keine Compilermeldungen, Programm startet)
Was mach ich grade falsch? Bzw was muss ich noch beachten?
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 08.03.10 15:19
Moin!
7h3_L!z4rD hat folgendes geschrieben : | Was mach ich grade falsch? Bzw was muss ich noch beachten? |
Den Code zeigen, wir können ja nicht hellsehen?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
7h3_L!z4rD 
Hält's aus hier
Beiträge: 5
WinXPPro
D7
|
Verfasst: Mo 08.03.10 22:04
Sorry... mein Fehler!
Die gespeicherten Daten aufm USB-Stick hats mir irgendwie zerhackt, so dass ich gerade das Ganze noch einmal gemacht habe.
Diesmal scheint es allerdings zu funktionieren...
Hauptunit ->
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, unit2;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; ListBox1: TListBox; procedure Button1Click(Sender: TObject); procedure TestFertig(Sender: TObject); procedure Button2Click(Sender: TObject); end;
var Form1: TForm1; WinTempDir: String; implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin ListBox1.Tag := -1; ListBox1.ItemIndex := -1; for i := 0 to ListBox1.Count-1 do TSpeedTestFTP.Create(ListBox1.Items.Strings[i],i,TestFertig); end;
procedure TForm1.TestFertig(Sender: TObject); begin ListBox1.Items.Objects[TSpeedTestFTP(Sender).Ref] := Pointer(TSpeedTestFTP(Sender).Speed); if (TSpeedTestFTP(Sender).Speed >= 0) then begin if (ListBox1.Tag = -1) or (TSpeedTestFTP(Sender).Speed < ListBox1.Tag) then begin ListBox1.Tag := TSpeedTestFTP(Sender).Speed; ListBox1.ItemIndex := TSpeedTestFTP(Sender).Ref; end; end; end;
procedure TForm1.Button2Click(Sender: TObject); begin Listbox1.Clear; Listbox1.Items.Add('127.0.0.1'); Listbox1.Items.Add('192.168.1.200'); end;
initialization Randomize; WinTempDir := IncludeTrailingPathDelimiter(GetEnvironmentVariable('TEMP')); if (WinTempDir = '') then begin SetLength(WinTempDir,MAX_PATH +1); SetLength(WinTempDir,GetTempPath(Length(WinTempDir),PChar(WinTempDir))); end; |
Thread-Unit ->
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73:
| unit Unit2;
interface
uses Classes, Windows, SysUtils, IdFTP;
type TSpeedTestFTP = class(TThread) private FHost: AnsiString; FRef: Integer; FSpeed: Integer; public constructor Create(const AHost: AnsiString; const ARef: Integer; AOnTerminate: TNotifyEvent); procedure Execute; override; property Host: AnsiString read FHost; property Ref: Integer read FRef write FRef; property Speed: Integer read FSpeed; end;
var WinTempDir: String;
implementation
constructor TSpeedTestFTP.Create(const AHost: AnsiString; const ARef: Integer; AOnTerminate: TNotifyEvent); begin inherited Create(TRUE); FHost := AHost; FSpeed := -1; FreeOnTerminate := TRUE; OnTerminate := AOnTerminate; Resume; end;
procedure TSpeedTestFTP.Execute; var FTP: TIdFTP; TempFile: String; Speed: Cardinal; begin FTP := TIdFTP.Create(NIL); try try FTP.Host := FHost; FTP.Port := 21; FTP.Username := 'anonymous'; FTP.Password := ''; FTP.Connect; TempFile := WinTempDir + Format('SpeedTest%x',[Random(MaxInt)]); Speed := GetTickCount; FTP.Get('\SPEEDTEST.TXT',TempFile,TRUE); FSpeed := GetTickCount - Speed; except FSpeed := -1; end; try FTP.Disconnect; DeleteFile(TempFile); except end; finally FTP.Free; end; end;
end. |
In beide Server wird sich korrekt eingeloggt und die entsprechende Datei heruntergeladen. - Vielen Dank erst einmal für die Hilfe bis hier her.
Allerdings ist mir noch nicht ganz klar, wie & wo die "Geschwindigkeiten" gespeichert werden & wie ich darauf zugreifen kann bzw. wie ich eine Rückmeldung für den schnellsten Server nach der Überprüfung bekomme.
Bisher habe ich es so aufgenommen, dass die Ticks in den Listbox1.Items.Objects[irgendwas] gespeichert werden... dabei ist .Object so zu verstehen, wie ein Array, bei dem die Indexe den entsprechenden Items zugeordnet werden. Wenn das so wäre, könnte ich also einfach eine kurze Überprüfung machen im Sinne von:
Delphi-Quelltext 1: 2: 3: 4:
| schneller := 0; from i := 1 to Listbox1.Count - 1 do if Listbox1.Items.Objects[schneller] > Listbox1.Items.Objects[i] then schneller := i; | (oder so ähnlich  )
und dann sagen Listbox1.Items[schneller] ist der aktuell schnellste Server...
Habe zwar nachgeschaut, was es so mit den Objects auf sich hat, aber es scheint bei jedem Beispiel etwas anders zu sein...
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Fr 12.03.10 13:59
Moin!
7h3_L!z4rD hat folgendes geschrieben : | Allerdings ist mir noch nicht ganz klar, wie & wo die "Geschwindigkeiten" gespeichert werden & wie ich darauf zugreifen kann
[...]
Bisher habe ich es so aufgenommen, dass die Ticks in den Listbox1.Items.Objects[irgendwas] gespeichert werden... dabei ist .Object so zu verstehen, wie ein Array, bei dem die Indexe den entsprechenden Items zugeordnet werden. |
So ist es, in den .Objects[] der Listbox-Items wird die Zeit in Ticks gespeichert, die für den Download benötigt wurde oder -1, wenn es irgend ein Problem gab.  Achtung Falle: kleinere Werte sind besser, Ausnahme: -1, das steht für einen Fehler!
7h3_L!z4rD hat folgendes geschrieben : | wie ich eine Rückmeldung für den schnellsten Server nach der Überprüfung bekomme. |
Dir ist dieses Stück Code aufgefallen?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.TestFertig(Sender: TObject); begin ListBox1.Items.Objects[TSpeedTestFTP(Sender).Ref] := Pointer(TSpeedTestFTP(Sender).Speed); if (TSpeedTestFTP(Sender).Speed >= 0) then begin if (ListBox1.Tag = -1) or (TSpeedTestFTP(Sender).Speed < ListBox1.Tag) then begin ListBox1.Tag := TSpeedTestFTP(Sender).Speed; ListBox1.ItemIndex := TSpeedTestFTP(Sender).Ref; end; end; end; | cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
|