Re: Beispiel zum Versenden von Dateien mit Indy
Wenn es jemanden hilft um mir helfen zu können
20KB werden übertragen und dann friert das ganze erst ein. Habe es mit mehreren Dateien ausprobiert die Ziel Datei ist immer nur 20KB groß bitte weiter um Hilfe. |
Re: Beispiel zum Versenden von Dateien mit Indy
Ich bitte um Hilfe es ist sehr Wichtig das das bei mit auch funktioniert.
Bitte, Bitte, Bitte helft mir doch. |
Re: Beispiel zum Versenden von Dateien mit Indy
Hi Jonny,
ich hab nur D5, sorry !! DA muss sich wohl jemand anderes erbahmen ! Gruß Data |
Re: Beispiel zum Versenden von Dateien mit Indy
Hallo hat hier denn niemand Delphi 7 Pro der das Programm für mich testen könnte und mir dann helfen könnte? Bitte!!!!
|
Re: Beispiel zum Versenden von Dateien mit Indy
Hi,
ich habe Delphi 7 pro und habe das selbe Problem, habe das Bsp auch genutzt! Bemerkt habe ich es alledings erst als ich eure Beiträge gelesen habe da ich die Projektdatei nie ausgeführt habe! Ich habe den Code nur als Hilfe für mein eigenes Projekt verwendet! Fakt ist: - Delphi 7 pro bau misst, nicht nur bei dir! um das Problem jedoch zu lösen, musst du lediglich den Code in eine neue Unit kopieren und die entsprechenden Kompos hinzufügen, voila es funkst, zumindest bei mir! Probier mal sonst kannste auch meinen code als Bsp haben! @wardz |
Re: Beispiel zum Versenden von Dateien mit Indy
Hm leider tut das auch nicht wenn ich das einfach so reinkopiere. Es wäre sehr nett wenn du mir deinen Code zurverfügung stellen würdest.
Bin jetzt schon Dankbar und hoffe das der funktioniert. |
Re: Beispiel zum Versenden von Dateien mit Indy
Ich will hier ja keinen hetzen aber ich würde den Code von ATwardz doch noch haben wollen.
Ist nicht bös gemeint aber ich brauche den wirklich dringend. |
Re: Beispiel zum Versenden von Dateien mit Indy
Ich verstehe nicht warum ihr nicht die Datei im ganzen in einem Rutsch senden wollt. Beim TCP/IP kann es zu keiner Datenverfälschung kommen und die Datenpackete treffen in der gleichen Reihenfolge ein wie sie vesendet wurden. Das bedeutet das man vom Server zum Clienten einen Header der den Dateinamen + Dateigröße und einen Datenblock der die Datei als ganzen enthält in einem Rutsch sendet. Wenn man unbedingt eine Überprüfung möchte so kann man hinter die Daten eine Prüfsumme anhängen. Der einzigste Fehler der auftreten kann ist ein Abbruch der Verbindung. Es wäre also hilfreich wenn der Client bei der Download-Anforderung eine Datei dort weiterladen kann wo abgebrochen wurde. Aber mehr müsste man eigentlich nicht berücksichtigen.
Wenn ihr eine Progressbar wollt dan geht auch dieses einfach. Nachdem der Header empfang en wurde wissen wir ja die Dateigröße der Daten die noch folgen. Also ließt man aus dem Socket nun Happen von 1024 Bytes und updatet die Progressbar. Allerdings beim INDY müsst ihr immer bedenken das JEDE Client/Server Conection im .Execute() in einem eigenen Thread läuft. Das heist beim Updaten der Gauge muß dies Threadfest sein. Übrigens, beim TCP/IP Protokoll ist es nicht zwingend das die Daten als TEXTE oder Textkommandos übertragen werden. Man kann auch einfach binäre Daten übertragen. Statt also einen aufwendigen Kommando-Text-Parser zu coden würde ein einzigstes Byte als Kommando/Response Code schon ausreichen. Gruß Hagen |
Re: Beispiel zum Versenden von Dateien mit Indy
Hast du denn ein Gutes Beispiel dafür? Bin nicht gerade Fit auf dem Gebiet "Indy".
Mir ist aufjedenfall Wichtig das der Server Mehrere Dateien Gleichzeitig empfangen kann und das er auch den (Download)-Status der dateien anzeigen kann und weiter ist mir wichtig das auch der Client den (Upload)-Status anzeigen kann also mit einer Progressbar oder so. |
Re: Beispiel zum Versenden von Dateien mit Indy
Ein konkretes Beispiel habe ich nicht, aber wie können es Step by Step durchgehen.
Zuerst bauen wir den Server und erklären dabei das benutzte Protokoll. Als erstes definieren wir was als wichtigstes und erstes in das projekt integeriert werden soll. Wir beschränken uns erstmal auf das Notwendigste, also keine Progressbar und nur Upload von Dateien vom Clienten aus den Server. Erzeuge neues Project und nenne es Server. Auf's Hauptformular bringste einen INDY TCP/IP Server drauf. Bei diesem stellste folgendes ein: .Bindings := 0.0.0.0:7000; .DefaultPort := 7000; .ReuseSockects := rsTrue; .Active := True; Zusätzlich ein TMemo mit Namen Memo1 und folgenden Eigenschaften: .Font := 'Courier New'; .Align := alClient; .Lines := ''; .WordWrap := False; .Scrollbars := ssBoth; Nun im OI in das Ereigniss .OnExecute ein Doppelklick. Wir landen im Sourceeditor und coden NUR diese eine Execute Methode, denn mehr benötigen wir erstmal garnicht. Damit klarer wird was wir möchten definieren wir aber erstmal unser Protokoll. Jede Kommunikation beginnt mit einem Kommando-Byte, somit stehen uns maximal 256 verschiedene Kommandos zur Verfügung. Per Definition legen wir folgende Kommandos fest: 0= NULL, heist keine Aktion und dient als Dummy Message um eventuell connections am leben zu erhalten 1= LOGIN, der Client sendet dieses Kommando IMMER als erstes, über dieses Kommando identifiziert sich ein Client und die Clientsoftware. Ein Server antwortet NUR auf eine solches korrektes Client Login. D.h. dieses Kommando MUSS das erste sein was der Server empfängt. Falls dies nicht der Fall ist trennt der Server sofort die Conection. 3= ERROR, Fehlerpacket 4= LOGOUT, der Client trennt die verbindung 5= UPLOAD, der Client sendet eine Datei, direkt nach dem Kommando-Byte folgen der dateiheader und die eigentliche Datei Der Server hat auf jedes Kommando mit einem Echo-Kommando zu bestätigen. D.h. wenn der Client das Kommando=1=LOGIN sendet antwortet der Server ebenfalls mit Kommando=1=Login bei Erfolg oder er antwortet mit Kommand=3=ERROR und trennt die Verbindung. Genauer werden wir erstmal das Protokoll nicht beschreiben, die Sourcen sollten es erklären. Nun der Code in OnExecute() sollte so aussehen:
Delphi-Quellcode:
Fertig ist der Server. Er sollte KEINERLEI Progressbars besitzen, da Server normalerweise unsichtbar im Hintergund laufen sollten.
var
LastSessionID: Integer = 1; procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); var SessionID: Integer; procedure DoLog(const Msg: String); var S: String; I: Integer; begin S := Format('%s-%0.6d: %s', [FormatDateTime('YYMMDD HHNNSS ZZZ', Now), SessionID, Msg]); for I := 1 to Length(S) do if S[I] in [#10,#13] then S[I] := ' '; // da Memo1.Lines.Add() intern über SendMessage() arbeitet sollte dies Threadsafe sein. Memo1.Lines.Add(S); end; function ReadByte: Byte; begin AThread.Connection.ReadBuffer(Result, SizeOf(Result)); end; function ReadLong: Cardinal; function SwapLong(Value: Cardinal): Cardinal; // konvertiert Big Endian zu Little Endian // im INet ist es üblich ALLE Daten in Big Endian zu übertragen asm BSWAP EAX end; begin AThread.Connection.ReadBuffer(Result, SizeOf(Result)); Result := SwapLong(Result); end; function ReadString: String; begin SetLength(Result, ReadByte); AThread.Connection.ReadBuffer(Result[1], Length(Result)); end; procedure WriteByte(Value: Byte); begin AThread.Connection.WriteBuffer(Value, SizeOf(Value)); end; procedure WriteString(const Value: ShortString); begin WriteByte(Length(Value)); AThread.Connection.WriteBuffer(Value[1], Length(Value)); end; var FileName: String; FileSize: Cardinal; FileStream: TStream; begin SessionID := LastSessionID; Inc(LastSessionID); try DoLog(Format('Client connect at IP ', [AThread.Connection.Socket.Binding.PeerIP])); if (ReadByte = 1) and (ReadString = 'MyUpload 1.0') then // LOGIN begin // Client hat sich korrekt identifiziert sende Bestätigung und warte auf Kommandos WriteByte(1); while True do case ReadByte of 0: begin // NULL WriteByte(0); end; 2: begin // LOGOUT DoLog('Client logout'); Break; end; 3: begin // ERROR DoLog(Format('Client error %d, %s', [ReadByte, ReadString])); Break; // Fehler fürht IMMER zum Abbau der Verbindung end; 4: begin // UPLOAD FileName := ExtractFilePath(ParamStr(0)) + 'Upload\' + ReadString; FileSize := ReadLong; DoLog(Format('Client upload %5d, %s', [FileSize, FileName])); try FileStream := TFileStream.Create(FileName, fmCreate); try AThread.Connection.ReadStream(FileStream, FileSize); finally FileStream.Free; end; WriteByte(4); except on E: Exception do begin WriteByte(3); // ERROR WriteByte(1); WriteString(E.Message); Break; end; end; end; else begin // Invalid Code; DoLog('Client sends unknown command, terminate'); WriteByte(3); WriteByte(0); // Errorcode WriteString('unknown kommand'); Sleep(1); Break; end; end; end; // falsches/fehlendens Client-Login, trenne einfach die Verbindung, Server ist im Stealth mode finally DoLog('Client terminated'); try Sleep(1); AThread.Connection.Disconnect; except end; end; end; Nun ein zweites neues Projekt für den Clienten erzeugen. Auf das Formular ein TidTCPClient mit Namen 'TCP' daruf und Eigenschaften: .Host := 'localhost'; .Port := 7000; .ReadTimeout := 5000; Zusätzlich noch einen TButton, TLabel, TProgressbar und TOpenDialog drauf. Im OnClick von Button1 steht dann folgendes:
Delphi-Quellcode:
Gruß Hagen
procedure TForm1.Button1Click(Sender: TObject);
procedure WriteByte(Value: Byte); begin TCP.WriteBuffer(Value, SizeOf(Value)); end; procedure WriteLong(Value: Cardinal); function SwapLong(Value: Cardinal): Cardinal; asm BSWAP EAX end; begin Value := SwapLong(Value); TCP.WriteBuffer(Value, SizeOf(Value)); end; procedure WriteString(const Value: String); begin WriteByte(Length(Value)); TCP.WriteBuffer(Value[1], Length(Value)); end; function ReadByte: Byte; begin TCP.ReadBuffer(Result, SizeOf(Result)); end; function ReadString: String; begin SetLength(Result, ReadByte); TCP.ReadBuffer(Result[1], Length(Result)); end; var I: Integer; SendSize,FileSize: Integer; FileName: String; FileStream: TStream; begin if OpenDialog1.InitialDir = '' then OpenDialog1.InitialDir := ExtractFilePath(ParamStr(0)); if OpenDialog1.Execute then try try TCP.Connect; WriteByte(1); WriteString('MyUpload 1.0'); case ReadByte of 1: begin for I := 0 to OpenDialog1.Files.Count -1 do try FileName := OpenDialog1.Files[I]; FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); try FileSize := FileStream.Size; WriteByte(4); WriteString(ExtractFileName(FileName)); WriteLong(FileSize); Label1.Caption := Format('sende %s', [Filename]); Label1.Update; ProgressBar1.Min := 0; ProgressBar1.Max := FileSize; ProgressBar1.Position := 0; while FileSize > 0 do begin SendSize := FileSize; if SendSize > 1024 then SendSize := 1024; Dec(FileSize, SendSize); TCP.WriteStream(FileStream, False, False, SendSize); ProgressBar1.Position := ProgressBar1.Position + SendSize; end; finally FileStream.Free; end; case ReadByte of 3: begin // fehler ShowMessage(Format('Fehler %5d, %s', [ReadByte, ReadString])); Break; end; 4: ; // alles Ok end; except on E: Exception do ShowMessage(E.Message); end; WriteByte(2); end; 3: begin ShowMessage(Format('Error %d, %s', [ReadByte, ReadString])); end; else ShowMessage('Invalid Responsecode'); end; finally TCP.Disconnect; end; except on E: Exception do ShowMessage(E.Message); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz