AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Dateien senden und empfangen
Thema durchsuchen
Ansicht
Themen-Optionen

Dateien senden und empfangen

Ein Thema von Karg · begonnen am 15. Nov 2007 · letzter Beitrag vom 20. Nov 2007
Antwort Antwort
Seite 1 von 2  1 2      
Karg

Registriert seit: 5. Jun 2007
36 Beiträge
 
#1

Dateien senden und empfangen

  Alt 15. Nov 2007, 18:57
hi @ all,
ich will über server und clientsocket eine datei senden bzw. empangen.
Jedoch funktioniert es nicht und ich komm nicht auf den fehler.
Hier mal der code:

Server sendet stream:
Delphi-Quellcode:
 //--------- DOWNLOAD FILE --------------
 if pos('<DOWNLOAD>',buf) <> 0 then
  begin
   DFile:=Tfilestream.Create(Fchosen,fmopenread); //Fchosen ist der pfad zur datei
   Dfile.Position:=0;
   DFile_size:= DFile.size; // var DFILE_size: int64;
   file_client.Socket.SendBuf(DFile_size,sizeof(int64));
   file_client.Socket.SendStream(Dfile);
   Dfile.Free;
  end;


Client empfängt:
Delphi-Quellcode:
DFile:=Tfilestream.Create('c:\test.exe',fmcreate or fmopenwrite);
  //---- Streamgröße ermitteln-----
   if socket.ReceiveLength <= sizeof(int64) then
    begin
     socket.ReceiveBuf(DFILE_SIZE,sizeof(DFILE_size)); // var DFILE_SIZE:int64;
    end;

   //---- Stream empfangen-----
   if Socket.ReceiveLength>sizeof(int64) then
     begin
       streamsize:=socket.ReceiveLength;
       getmem(buffer,streamsize);
        try
         socket.ReceiveBuf(buffer^,streamsize);
         Dfile.WriteBuffer(buffer^,streamsize);
        finally
         freemem(buffer); end;
         
      if Dfile.size>=Dfile_size then Dfile.Free;
      end;
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#2

Re: Dateien senden und empfangen

  Alt 15. Nov 2007, 21:24
1. Delphi-Referenz durchsuchenSendStream() siehe Hilfe: Du darfst den Stream nicht freigeben. SendStream übernimmt diesen und gibt ihn frei, wenn er ihn versendet hat (was er im Hintergrund erledigt)
2. if socket.ReceiveLength <= sizeof(int64) then Ach, wenn du also noch keine 8 Bytes für den Int64 empfangen hast, also z.B. nur ein Byte, dann liest du den Int64 auch schon aus? Warum nimmst du dann einen Int64, wenn doch anscheinend auch schon alles in 0 Bytes oder vllt. einem Byte hinein passt?
3. Du öffnest im OnClientRead ständig den FileStream mit fmCreate. Wenn du schon etwas in die Datei reingeschrieben hast, dann wird dies überschrieben.
4. Beachte: Du wirst öfters im OnClientRead aufgerufen bis du die Datei komplett empfangen hast. Die Daten kommen häppchenweise an (wie du sie losschickst ist egal, ob als Stream oder auch irgendwie aufgeteilt). Von daher solltest du nicht mitten im Datenstrom nochmals einen Int64 auslesen oder die Datei erneut öffnen und somit überschreiben.

Ich denke mal mit den Hinweisen bekommst du eine lauffähige Version hin...
  Mit Zitat antworten Zitat
Karg

Registriert seit: 5. Jun 2007
36 Beiträge
 
#3

Re: Dateien senden und empfangen

  Alt 16. Nov 2007, 18:58
also, erstmal vielen dank für die schnelle hilfe.
Allerdings hab ich es immer noch nicht zum laufen gebracht und ich dreh bald durch.

hier mein neuer versuch:


client:
Delphi-Quellcode:
type
 TDownload = (fileverwaltung,download);
var filemode:TDownload;


procedure TForm9.download1Click(Sender: TObject);
begin
Dfile:=tfilestream.Create('c:\test.txt',fmcreate);
form1.file_server.Socket.Connections[0].SendText('<DOWNLOAD>' + Pfad); //hier wird der pfad an den server geschickt
end;


procedure TForm1.file_serverClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
case filemode of
//---- Streamgröße ermitteln-----
  fileverwaltung:begin
                   if pos('<FILEONWAY>',buf) <> 0 then
                   begin
                    DFile_size:=0;
                    Dfile_size:=strtoint(copy(buf,pos('<FILEONWAY>',buf)+11,999));
                    showmessage(inttostr(Dfile_size));
                    filemode:=download;
                   end;
              end;

 //---- streampakete empfangen und in stream schreiben-----
  Download: begin
              streamsize:=file_server.Socket.Connections[0].ReceiveLength;
             getmem(buffer,streamsize);
              try
               File_server.socket.Connections[0].ReceiveBuf(buffer^,streamsize);
               Dfile.WriteBuffer(buffer^,streamsize);
              finally
               freemem(buffer); end;
             if Dfile.size>=Dfile_size then Dfile.Free;
             end;
  end;

server:
Delphi-Quellcode:
procedure TForm1.file_clientRead(Sender: TObject;
  Socket: TCustomWinSocket);
begin
//--------- DOWNLOAD FILE --------------
 if pos('<DOWNLOAD>',buf) <> 0 then
  begin
  Fchosen:=copy(buf,pos('<DOWNLOAD>',buf)+10,999); //Fchosen ist der vom client gesendete Pfad
  DFile:=Tfilestream.Create(fchosen,fmopenread);
  Dfile_size:=Dfile.size;
  file_client.Socket.SendText('<FILEONWAY>'+inttostr(Dfile_size));
  sleep(200);

  file_client.Socket.SendStream(Dfile);
  end;
end;
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#4

Re: Dateien senden und empfangen

  Alt 16. Nov 2007, 20:34
Ok, dann mal weiter mit den Listen...

1. Du greifst von TForm9 auf TForm1 zu - sehr böse...
2. Globale Variable filemode? Die passt auch in das Formular Form1 o.ä.
3. Im Download1Click solltest du filemode auf fileverwaltung setzen - wenn nicht gerade ein Download läuft (z.B. erkennbar, wenn der Stream <> nil ist)
4. Es ist sehr schlechter Stil, wenn du immer wieder auf die erste Verbindung vom Server zugreifst. Wie willst du denn jemals andere Clients auseinander halten? Nutze die in der OnClientRead Methode übergebene Socket Instanz, diese ist immer genau der Socket aus dem Connections[] Array, für den er was empfangen hat.
5. Deine OnClientRead scheint gekürzt zu sein. Ich sehe nicht wo du "buf" füllst. Vor allem stellt sich mir die Frage, wie du das machst. Ich vermute ReceiveText - dies wäre aber in deinem Falle eine mehr als schlechte Wahl, da du Text und Binärdaten mischt. ReceiveText gibt dir alles im Puffer existierende als String zurück - dabei macht der Socket keine Unterscheidung ob das Daten oder Texte sind - das weiss er schliesslich nicht. Darum musst du dich kümmern und entsprechend ein Protokoll bauen. Das hast du soweit auch gemacht, aber da es Text ist, hast du ein Problem. Wenn er nun "<FILEONWAY>1024smdgjkg hjkghwjk" empfängt, was machst du denn? Die "smdgjkg hjkghwjk" sind schon der Anfang der Dateidaten. Ich hatte dir schon zuvor geschrieben, dass es keine Reihenfolge gibt, wie du die Daten empfängst. Dein Sleep beim senden ist zwar recht nett, nützt aber überhaupt nichts. Es funktioniert bei dir lokal oder vllt. noch im LAN, aber das wars dann auch.
6. Wenn du mit ReceiveText buf empfängst im OnClientRead, dann hast du dort jedesmal schon Teile der Datei (alles was er derzeit empfangen hat) im string von ReceiveText. Danach wäre es Glück, wenn er nebenbei noch wieder was empfangen hat und somit ReceiveLen wieder > 0 ist.
7. Wie schon zuvor erwähnt: Sleep(200) ist völlig nutzlos und irrelevant beim Server. Er sendet die Daten und wenn dein Netzwerk mal etwas belastet ist, werden die Daten eh zusammen geschmiert. DU musst das ganze teilen - nun weiss mal wo. Wieviele Zeichen ist denn die Dateigrösse lang? Wieviel Zeichen willst du einlesen ohne schon bytes von der Datei zu lesen?
  Mit Zitat antworten Zitat
Karg

Registriert seit: 5. Jun 2007
36 Beiträge
 
#5

Re: Dateien senden und empfangen

  Alt 17. Nov 2007, 11:24
ah ok, jetzt versteh ich das problem.
vielen dank. ich werd es gleich mal testen...
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#6

Re: Dateien senden und empfangen

  Alt 18. Nov 2007, 07:14
wenn du dann einen funktionierenden Quellcode hast, wärst du dann so nett und stellst ihn hier rein?

rollstuhlfahrer
Bernhard
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#7

Re: Dateien senden und empfangen

  Alt 18. Nov 2007, 13:57
Zitat von rollstuhlfahrer:
wenn du dann einen funktionierenden Quellcode hast, wärst du dann so nett und stellst ihn hier rein?
Daran soll's nicht liegen, da habe ich hier auch welche. Aber der nächste würde nur abschreiben so lernt er durch den Thread die Hintergründe seines scheiterns und kann mit diesem neuen Wissen den Code umbauen. Dabei lernt er mehr (vor allem da er es selber macht) als wenn er such, diesen Thread findet und den kompletten Code kopiert...
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#8

Re: Dateien senden und empfangen

  Alt 18. Nov 2007, 18:16
Also, mein Problem ist:
Ich will ein Bitmap über ServerSocket->ClientSocket versenden. So ein bissel Quelltext hab ich schon:

Server
Delphi-Quellcode:
    Bild := TBitmap.Create; // Das Bitmap zum Versenden
    MS := TMemoryStream.Create; // Der dazugehörige Stream
    MakeScreenShot(Bild);
    Bild.SaveToFile('C:\temp.bmp');
    Bild.SaveToStream(MS);
    MS.Write('ENDE', 4);
    MS.Position := 0;

    ServerSocket1.Socket.Connections[0].SendStream(MS);
Das hier gespeicherte Bild ist nicht beschädigt und lässt sich öffnen

Client
Delphi-Quellcode:
var
  Form1: TForm1;
  MS: TMemoryStream;

procedure TForm1.Button6Click(Sender: TObject);
begin
if ClientSocket1.Active then
  ClientSocket1.Socket.SendText('SCREENSHOT'); // Anfrage senden

  MS := TMemoryStream.Create;
  MS.Position := 0;
end;

procedure TForm1.ClientSocket1Read(Sender: TObject); // Rückgabe (wird rund 670 mal aufgerufen)
  Socket: TCustomWinSocket);
var text, reststr: string;
begin
  text := Socket.ReceiveText;
  begin
    Label8.Caption := IntToStr(StrToInt(Label8.Caption)+1);
    
    if Pos('ENDE', text) = 0 then
      MS.Write(text, Length(text))
    else
    begin
      MS.Write(text, Length(text) - 4);
      MS.Position := 0;
      MS.SaveToFile('C:\temp_client.bmp');
      MS.Position := 0;
      Image1.Picture.Bitmap.LoadFromStream(MS);
      MS.Free;
     end;
  end;
Das hier resultierende Bitmap ist beschädigt und fehlerhaft.
Im Hex-Editor enthält dieses Bitmap folgende Zeichenkette, die rein gar nichts mit dem Ursprung zu tun hat (der Bitmap-Header fehlt auch):
Microsoft Windows GdiPlus ProcessorArchitecture="x86"

Keine Ahnung, wo das herkommt

rollstuhlfahrer
Bernhard
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#9

Re: Dateien senden und empfangen

  Alt 18. Nov 2007, 22:16
Ui, na Hilfe.

Du hast den Thread aber soweit schonmal durchgelesen und nicht einfach nur einen neuen Beitrag angehangen? Schliesslich ist ein in diesem Thread schon dargestelltes Problem von dir genauso gemacht worden. Also auch mal für dich eine Liste:

1. Der Socket überträgt einfach nur Daten. Er weiss nicht, welches Format sie haben noch was für ein Typ sie sind. Du kannst einen String reinstecken (SendText()) und ihn als Binärdaten auf der anderen Seite wieder auslesen. Der Socket weiß nicht das es ein String ist. Für ihn sind es einfach nur Daten - eine Abfolge von Bytes. Was die Bytes bedeutet bzw. welche Bytes zusammengehören und was darstellen, weiss er nicht: Der Socket ist ein reines Übertragungsmittel. Er hält nur die Reihenfolge der Bytes ein. In der Reihenfolge wie die Bytes reingesteckt werden, in der Reihenfolge kommen sie wieder raus. Und auch die Idee, dass ein mit SendText() gesendeter String am Ende wieder als String rauskommt oder abgetrennt von den nachfolgenden Daten ankommt, ist ein Irrglaube. Der Socket überträgt die Bytes und weiss nicht wo was aufhört und wie was versendet wurde. Das muss ein Protokoll erledigen und das hast du dir auszudenken.
2. Warum definierst du dir eine globale Variable MS? Spricht auch nur irgendwas kleines dagegen diese in der Form als Member zu deklarieren?
3. Die Eigenschaft Position ist bei einem neu angelegten Stream schon auf 0.
4. Du rufst gleich als erstes Socket.ReceiveText auf. Und nun mach dich in diesem Thread nochmal schlau, was ReceiveText dir denn alles zurück gibt. Dann meld dich nochmal...
5. Du gibst als Stelle der Daten für den TStream.Write() den String an. Der String ist nur die Adresse wo die Zeichenkette steht, somit schreibt die TStream.Write() Methode alles ab der Adresse wo der String steht und nachfolgenden in den Stream - aber nicht deine Daten.

/EDIT: Sorry, wenn es überheblich rüberkommt, aber der Quellcode hat zwei hauptsächliche Fehler. Der eine ist zu Hauf in Bezug auf das Schreiben von Strings in einen TStream Nachfahren hier behandelt worden. Pro Monat im Schnitt zwei mal. Das andere Hauptproblem wurde genau zwei Posts zuvor in diesem Thread beschrieben. Von daher wirkt meine Antwort etwas überheblich, aber ich war gedanklich beim . Aber unabhängig davon: Ich helfe trotzdem gerne weiter.
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#10

Re: Dateien senden und empfangen

  Alt 19. Nov 2007, 15:06
Danke für die nette (nicht falsch verstehen) Hilfe!
Ich hab ein paar Entwicklungen auf Clientseite gemacht:
Der Stream wurde duch eine einfache Dateiprozedur mit AssignFile()->Rewrite()/Append()->Write->CloseFile() ersetzt.
Das Bild kommt jetzt sauber an. Das einzige Problem dürfte jetzt noch sein, dass Server und Client auf dem selben Rechner laufen. Die Screenshots bekommen alle eine unerwünschte Rückkopplung (wenn man das Bild aufnimmt ...)

rollstuhlfahrer

PS: Kleine Änderungen:

Delphi-Quellcode:
procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var text, reststr: string;
    f: textfile;
begin
    if Pos('ENDE', text) <> 0 then
      text := System.Copy(text, Pos('ENDE', text)-1, Length(text)-4);

    AssignFile(f, 'C:\temp_client.bmp'); // Filename
    if FileExists('C:\temp_client.bmp') then
      Append(f)
    else
      Rewrite(f); // Datei existiert beim ersten Aufrufen noch nicht

    Write(f, text);
    CloseFile(f);
  end;
Bernhard
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 16:10 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