AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi beliebige Datei in Stream speichern
Thema durchsuchen
Ansicht
Themen-Optionen

beliebige Datei in Stream speichern

Ein Thema von Evilboyz · begonnen am 27. Jan 2003 · letzter Beitrag vom 4. Nov 2003
Antwort Antwort
Seite 2 von 3     12 3      
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.116 Beiträge
 
Delphi 11 Alexandria
 
#11
  Alt 28. Jan 2003, 17:34
Moin Evilboyz,

in Deinem Beispiel fehlt die Initialisierung des Buffers, ausserdem muss, wenn der Buffer ein String ist zwingend die Position angeben werden, ab der aus dem Buffer gelesen, bzw. ab der in den Buffer geschrieben werden soll. Ausserdem ist TStream eine abstrakte Klasse, die man nur als Basisklasse für Ableitungen eigener Klassen nutzen sollte (wenn Du hier im Forum mal nach "abstrakt" suchst, solltest Du dazu eine Nähere Erklärung finden):

Delphi-Quellcode:
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

var
  fsData : TFileStream; // Nur mal als Beispiel einen FileStream angenommen
  sBuffer : String;
begin
  // FileStream zum Schreiben öffnen
  fsData := TFileStream.Create('IrgendeinDateiPfad',fmOpenWrite);
  try
    // Buffer initialisieren (erst hier. Falls TFileStream.Create schiefgeht, muss der Buffer ja nicht initialisiert sein
    sBuffer := StringOfChar(#00,Socket.ReceiveLength);
    // Da in der Maximallänge gelesen wird, braucht man keine Schleife
    // Wichtig: sBuffer[1], damit an der ersten Stelle des Buffers geschrieben wird
    if Socket.ReceiveBuf(sBuffer[1],Socket.ReceiveLength) <> -1 then
    begin
      // Eingelesene Daten in Datei wegschreiben, wenn etwas eingelesen wurde
      fsData.Write(sBuffer[1],Length(sBuffer));
    end;
  finally
    // Stream wieder freigeben
    FreeAndNil(fsData);
  end;
end;
Ich hab' Dein Beispiel mal "ergänzt".
So müsste es eigentlich gehen. Schau doch mal, ob Du damit klarkommst.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Evilboyz

Registriert seit: 14. Jan 2003
78 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#12
  Alt 29. Jan 2003, 11:54

Es funktioniert!!!! Vielen Dank für die Hilfe!

Eine kleine Anmerkung habe ich allerdings noch. Da die Datei in mehreren Blöcken empfangen wird, ist es wichtig, darauf zu achten, dass der Zeiger im FileStream vor dem Schreiben jedes Blocks am Ende steht!
Code:
fsData.Seek(0, SoFromEnd);
Ansonsten wird die Datei niemals größer als 3 KB ...
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.116 Beiträge
 
Delphi 11 Alexandria
 
#13
  Alt 29. Jan 2003, 13:27
Moin Evilboyz,

Zitat von Evilboyz:
Ansonsten wird die Datei niemals größer als 3 KB ...
Das spart dann aber ungeheuer Platz
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Benutzerbild von Jan
Jan

Registriert seit: 24. Sep 2002
Ort: Magdeburg
491 Beiträge
 
Delphi 7 Enterprise
 
#14
  Alt 29. Jan 2003, 18:16
Hi ihrs!
Ich hab das jetzt mal Interressehalber nachgemacht, und sitze da jetzt schon ca 3 stunden dran, so langsam.....
Naja, guckt euch das vielleicht mal an:

Server:

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp;

type
  TForm1 = class(TForm)
    ServerSocket1: TServerSocket;
    procedure ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
     recbuffer:string;
     recstream:tfilestream;
begin
  recbuffer:=stringofchar(#00,socket.ReceiveLength);
  try
     socket.ReceiveBuf(recbuffer[1], length(recbuffer));
    recstream:=tfilestream.create('c:\test.exe', fmopenwrite);
    recstream.Write(recbuffer[1], length(recbuffer));
  finally
     freeandnil(recbuffer);
    freeandnil(recstream);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
serversocket1.Active:=true;
serversocket1.Open;
end;

end.

Client:

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp;

type
  TForm1 = class(TForm)
    ClientSocket1: TClientSocket;
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
  if opendialog1.Execute then
  begin
    edit2.Text:=form1.OpenDialog1.FileName;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
     meanfile : tfilestream;
     meanbuffer : string;
begin
  if (edit1.Text<>'') and (edit2.text<>'') then
  begin
    try
      clientsocket1.Address := edit1.Text;
    except
      showmessage('geben sie eine gültige IP-Addresse an!');
    end;
    clientsocket1.active:=true;
    meanfile:=tfilestream.create(edit2.text, fmopenread);
    meanbuffer:=stringofchar(#00, meanfile.size);
    try
      meanfile.read(meanbuffer[1], length(meanbuffer));
      clientsocket1.Open;
      if form1.ClientSocket1.socket.Sendbuf(meanbuffer, length(meanbuffer))<>-1 then
        showmessage('Datei erfolgreich verschickt');
    finally
      freeandnil(meanfile);
      clientsocket1.close;
      clientsocket1.Free;
    end;
  end;
end;

end.
Ich erhalte beim Schicken einer Datei beim Servertool einen error unbekannter Herkunft (10052) und einen "asyncronous socket error" aber ich habe eigentlich bei beiden Programmen den Port auf 22 gestellt.
*Helpneed*
Also danke schonmal für alle Antworten!
BB!
Jan
Jan
Wenn die Sonne der Kultur tief steht, werfen auch kleine Gestalten lange Schatten.
  Mit Zitat antworten Zitat
Evilboyz

Registriert seit: 14. Jan 2003
78 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#15
  Alt 30. Jan 2003, 08:58
Hallo Jan,

also grundsätzlich konnte ich in Deinem Code mal keinen Fehler entdecken. Fehler 10052 bedeutet laut Delphi Hilfe "Verbindung pausiert, wenn SO_KEEPALIVE gesetzt wird." .... Soweit ich mich erinnern kann, hatte ich den Fehler auch hin und wieder, wenn eine Seite des Programms unplanmäßig beendet wurde.
Ansonsten hast Du, um die Verbindung aufzubauen, Socket.open verwendet, ich habe das über socket.active := true gemacht, aber das kann ja eigentlich keinen Unterschied machen!
Außerdem habe ich (siehe weiter oben) den Filestream vor dem schreiben beim Empfänger auf die letzte Position gesetzt. Das hat zwar sicher nichts mit Deinem Problem zu tun, allerdings habe ich damit noch ein Problem! Und zwar wird die Datei bei mir wunderbar übertragen, allerdings schleichen sich beim Schreiben dann falsche Bits, nämlich die der Bufferinitialisierung, ein, wenn meine Datei über 100 KB hat. Hat einer eine Idee, woran das liegen könnte?
Ich poste einfach mal meinen Code ... @jan: Vielleicht hilft er Dir ja weiter!?!

Server (Dateisender):
Code:
procedure TForm1.ServerSocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var fsWork : TFileStream;
      sBuffer, sIncome : String;
begin
     sIncome := Socket.ReceiveText;

     if sIncome='GetUpdate' then begin
          fsWork := TFileStream.Create('datei\bindif.exe', fmOpenRead);
          sBuffer := StringOfChar(#0,fsWork.Size);
          try
             // Komplett in Buffer einlesen
             fsWork.Read(sBuffer[1],fsWork.Size);
          finally
             FreeAndNil(fsWork);
          end;
          if Socket.SendBuf(sBuffer[1],Length(sBuffer))=-1 then
             showMessage('Es konnte keine Datei übertragen werden')
          else begin
              Events.Lines.Add('Datei wurde erfolgreich an Client übertragen');
          end;
     end
end;

procedure TForm1.ConnectClick(Sender: TObject);
begin
     ServerSocket.Port := StrToInt(Port.Text);
     ServerSocket.active := true;
     PageControl.ActivePage := TabSheet1;
end;

procedure TForm1.DisconnectClick(Sender: TObject);
begin
     ServerSocket.active:=false;
     Events.Lines.Add('Server disconnected');
     Clients.Text := '0';
end;
Client (Dateiempfänger):
Code:
procedure TForm1.ConnectClick(Sender: TObject);
begin
    ClientSocket1.Port := StrToInt(Port.Text);
    ClientSocket1.Host := Host.Text;
    ClientSocket1.active := true;
end;

procedure TForm1.DisconnectClick(Sender: TObject);
begin
     ClientSocket1.Active:=false;
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  fsData : TFileStream;
  sBuffer : String;
begin
  fsData := TFileStream.Create('datei\bindif.exe',fmOpenWrite);
  try
    sBuffer := StringOfChar(#23,Socket.ReceiveLength);
    if Socket.ReceiveBuf(sBuffer[1],Socket.ReceiveLength) <> -1 then
    begin
      fsData.Seek(0, SoFromEnd); //Hier scheint irgendwie noch ein
                                 //Problem aufzutreten
      fsData.Write(sBuffer[1],length(sBuffer));
      Events.Lines.Add('Datenblock empfangen');
    end;    
  finally
    FreeAndNil(fsData);
  end;
end;
  Mit Zitat antworten Zitat
Evilboyz

Registriert seit: 14. Jan 2003
78 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#16
  Alt 30. Jan 2003, 14:52
So, wunderschönen guten Tag Euch allen
Es funktioniert nun tatsächlich!
Ich sende meinen FileStream jetzt per SendStream:
Code:
fsWork := TFileStream.Create('datei\bindif.exe', fmOpenRead);
sBuffer := StringOfChar(#0,fsWork.Size);
fsWork.Seek(0, soFromBeginning);
Socket.SendStream(fsWork);
Empfangen tue ich das ganz primitiv über ReceiveText:
Code:
sBuffer := Socket.ReceiveText;
fsData.Write(sBuffer[1],Length(sBuffer));
Da das ganze tatsächlich so einfach funktioniert, stelle ich mir natürlich die Frage, ob ich irgendwas noch nicht bedacht habe. Spricht irgendetwas gegen diese Vorgehensweise?
Natürlich ist mir immer noch nicht klar, warum die andere Variante nicht funktioniert hat und da ich ein wissbegieriger Mensch bin, würde mich das trotzdem noch interessieren ....
In jedem Fall: Danke mal für Eure Hilfe ...
  Mit Zitat antworten Zitat
Benutzerbild von Jan
Jan

Registriert seit: 24. Sep 2002
Ort: Magdeburg
491 Beiträge
 
Delphi 7 Enterprise
 
#17
  Alt 30. Jan 2003, 17:16
Hallo evilboyz,
warum initialisierst du denn beim sender eigentlich noch den Buffer? Den brauchst du doch nichtmehr. Könntest du vielleicht mal den kompletten qtext von dir hier zeigen, vielleicht als attachment wenn er sonst zu lang ist. Ich komme bei mir einfach nichtmehr weiter. Wenn ich den Server schliesse, also quasi ins nimmerland schicke, dann bekomme ich keinen error beim sender, aber wenn ich den server laufen lasse, dann kommt beim server etwas an, aber der sender bekommt eine errormessage.

Kannst du mir mal sagen, warum du den server senden lässt und den client empfangen? normalerweise geht sowas andersrum. Deswegen komme ich auch mit deinen events nicht so ganz zurecht.
So long
Jan
Jan
Wenn die Sonne der Kultur tief steht, werfen auch kleine Gestalten lange Schatten.
  Mit Zitat antworten Zitat
Evilboyz

Registriert seit: 14. Jan 2003
78 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#18
  Alt 30. Jan 2003, 18:58
hi Jan,

der Server sendet in meinem Fall eine Datei als Antwort auf eine Clientanfrage. Den Code kann ich Dir morgen früh posten, da ich ihn gerade nicht hier habe, sind aber echt auch nur noch 3 oder 4 Zeilen (siehe letzter Beitrag).
Den Verbindungsaufbau mache ich ganz standardmäßig, indem ich einfach .active auf true setze und vorher die Werte für Port und IP zuweise.
Testest Du das ganze eigentlich lokal oder direkt schon übers Netz? Ich hatte nämlich bisher relativ viele Probleme mit Firewalleinstellungen und ich könnte mir vorstellen, dass sich in einem solchen Fall das Programm mit einem Fehler verabschiedet!
Aber wie gesagt, wenn es bei Dir bis morgen nicht läuft, kann ich Dir den Code nochmal geben.
  Mit Zitat antworten Zitat
Benutzerbild von Jan
Jan

Registriert seit: 24. Sep 2002
Ort: Magdeburg
491 Beiträge
 
Delphi 7 Enterprise
 
#19
  Alt 30. Jan 2003, 19:24
Hallo evil,
ich teste das lokal(127.0.0.1).
Und ich brauch echt morgen dann mal deinen code. Weil ich am verzweifeln bin, es wird immer nur eine 4k grosse datei geschrieben, und wenn ich den stream beim sender freigebe dann sifft das tool.
Alles sehr seltsam.
BB
Jan
Jan
Wenn die Sonne der Kultur tief steht, werfen auch kleine Gestalten lange Schatten.
  Mit Zitat antworten Zitat
Evilboyz

Registriert seit: 14. Jan 2003
78 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#20
  Alt 31. Jan 2003, 09:28
Hi,

ich vermute mal stark, dass Du vergessen hast, den Zeiger des Dateistreams auf die letzte Position zu setzen, dann schreibt er nämlich immer von erster Stelle und kommt nie über 4 KB.

Sender:
Code:
unit Client_Server;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ScktComp, ComCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    ServerSocket: TServerSocket;
 [...]
    procedure ConnectClick(Sender: TObject);
    procedure DisconnectClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.ServerSocketClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
     Events.Lines.Add('Client Connectet');
     Clients.Text := IntToStr(StrToInt(Clients.Text)+1);
end;

procedure TForm1.ServerSocketClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
     Events.Lines.Add('Client Disconnected');
     Clients.Text := IntToStr(StrToInt(Clients.Text)-1);
end;

procedure TForm1.ServerSocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var fsWork : TFileStream;
      sIncome : String;
begin
     // Anfrage von Client annehmen
     sIncome := Socket.ReceiveText;

     if sIncome='GetFile' then begin
          // Datei in Stream laden
          fsWork := TFileStream.Create('datei\bindif.exe', fmOpenRead);
          fsWork.Seek(0, soFromBeginning);
          // Stream als Antwort an Client senden
          if Socket.SendStream(fsWork) then begin
             Events.Lines.Add('Datei wurde erfolgreich an Client übertragen');
          end else
              Events.Lines.Add('Ein Fehler ist aufgetreten, die Datei konnte nicht gesendet werden');
     end
     else begin
          Events.Lines.Add(sIncome);
     end;
end;

procedure TForm1.ConnectClick(Sender: TObject);
begin
     ServerSocket.Port := StrToInt(Port.Text); //Festlegung des Ports
     ServerSocket.active := true; //Aktivierung der ServerSocket
     Events.Lines.Add('Server connected on Port ' + Port.Text);
     PageControl.ActivePage := TabSheet1;
end;

procedure TForm1.DisconnectClick(Sender: TObject);
begin
     ServerSocket.active:=false;
     Events.Lines.Add('Server disconnected');
     Clients.Text := '0';
end;

end.
Empfänger:
Code:
unit Client_Server;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ScktComp;

type
  TForm1 = class(TForm)
    Eingabe: TEdit;
    Button: TButton;
    ClientSocket1: TClientSocket;
    Eventlog: TGroupBox;
 [...]
TCustomWinSocket);
    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.ButtonClick(Sender: TObject);
begin
     if ClientSocket1.Active then
        ClientSocket1.Socket.SendText(Eingabe.text);
end;

procedure TForm1.ConnectClick(Sender: TObject);
begin
    ClientSocket1.Port := StrToInt(Port.Text); //Festlegung des Ports
    ClientSocket1.Host := Host.Text; //IP des Zielrechners
    ClientSocket1.active := true; //Aufbau der Verbindung

procedure TForm1.DisconnectClick(Sender: TObject);
begin
     ClientSocket1.Active:=false;
     Events.Lines.Add('Disconnected');
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  fsData : TFileStream;
  sBuffer : String;
begin
  // FileStream zum Schreiben öffnen
  fsData := TFileStream.Create('datei\bindif.exe',fmOpenWrite);
  sBuffer := StringOfChar(#00,fsData.Size);
  try
      // Dateiinhalt als String empfangen und in Datei schreiben
      sBuffer := Socket.ReceiveText;
      fsData.Seek(0, SoFromEnd);
      fsData.Write(sBuffer[1],Length(sBuffer));
      Events.Lines.Add('Datenblock empfangen');
  finally
      FreeAndNil(fsData);
  end;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  fsEmpty : TFileStream;
begin
  if FileExists('datei\bindif.exe') then
     DeleteFile('datei\bindif.exe');
  fsEmpty := TFileStream.Create('datei\bindif.exe',fmCreate);
  fsEmpty.Free;
end;

end.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:15 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