Autor Beitrag
alleinherrscher
Hält's aus hier
Beiträge: 11



BeitragVerfasst: So 21.11.04 16:07 
Hi@all

Ich benutzte den Standard - Indy - Code für das senden von Dateien von Client an Server, allerdings habe ich folgendes Problem: Auf dem einen Rechner ist Windows 2000, auf dem anderen 98. Auf einem dritten ist NT4.
Wenn ich dateien von 2000 nach 98 über mein Programm schicke, läuft alles wie vorgesehen, wenn ich allerdings von 98 auf 2000 oder NT Daten (also filestream) schicke, hängt sich der 98 - Client bei Dateien die größer als 0,5mb sind, auf...jemand ne ahnung warum? Auf beiden Rechner kommt exakt das gleiche Programm zur Anwendung!

Zwischen 2000 und NT ist das Daten schicken absolut kein Problem.

Hier die entsprechenden Routinen:


Der Client-Code:
ausblenden Delphi-Quelltext
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:
  Idtcpclient1.writeln('~fsm'+opendialog1.filename); <--Hier wird dem Server der Dateiname übergeben

memo1.lines.add('Trying to send File '+filename1 + ' to the remote computer');

  with IdTCPClient1 do
  begin

    fs := TFileStream.Create(filename1, fmOpenRead); //Datei in FileStream einlesen
     try
      OpenWriteBuffer; //stellt sicher, dass alle Daten versendet werden
      try
       WriteStream(fs, true, true); <--- Hier bleibt Windows 98 hängen!!!
        CloseWriteBuffer;
      except
        CancelWriteBuffer;
        raise;
      end;
    finally
      fs.Free;
      Disconnect;
    end;
      memo1.lines.add('Transfer done!');
  end;


end;


Entsprechend der ServerCode (Client und Server sind in einem Programm untergebracht):

ausblenden volle Höhe Delphi-Quelltext
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:
  text:=AThread.Connection.ReadLn();

typ:=copy(text,0,4);

if typ='~fsm' then begin
dateiname:=copy(text,pos('~fsm',text)+4,length(text)-4);
dateiname:=extractfilename(dateiname);
filename1:=dateiname;
endung:=copy(dateiname,pos('.',dateiname),length(dateiname)-pos('.',dateiname)+1);
savedialog1.FileName:=filename1;
savedialog1.Filter:=(endung+'|'+endung);


//FILES EMPFANGEN
with AThread.Connection do
    try
     fs := TFileStream.Create('C:\filestream.tmp', fmCreate or fmShareExclusive);
            SizeOfIncomingStream := ReadInteger; //Größe des Streams empfangen
      ReadStream(fs, SizeOfIncomingStream); //und übergeben
    finally
      fs.Free;
      streamsend:=False;
      Disconnect;
      end;

    AThread.Synchronize(speichern_unter);



exit;
end;


Wäre cool wenn jemand ne Idee hätte, hab allerseits die Indy Version 9.00.17.src und hoffe, ich muss keine andere installieren, weil das ja immer nen Aufstand ist...

:wink: Liebe wochenendlichen Grüße,

Euer Alleinherrscher
r4id3n
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 115

Win XP Home, Win XP Pro
D6 Prof, D7 Ent, K3 Ent
BeitragVerfasst: So 21.11.04 21:17 
Du solltest versuchen die Datei nicht in einem rutsch zu senden, sondern einzelne "Packete" daraus zu machen!
Lese dazu am besten z.b. jedes mal 10 - 100 kb der datei und sende diese einzeln ....
alleinherrscher Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mo 22.11.04 15:16 
Titel: Packete sind genial!
r4id3n hat folgendes geschrieben:
Du solltest versuchen die Datei nicht in einem rutsch zu senden, sondern einzelne "Packete" daraus zu machen!
Lese dazu am besten z.b. jedes mal 10 - 100 kb der datei und sende diese einzeln ....


Hey, die Idee ist gut! Nur....wie muss ich meinen source umschreiben? habe mir zu diesem Thema gerade ein Beispiel ausm netz gezogen, allerdings verstehe ich da nur bahnhof :shock:

Jemand ne Idee, wie ich das möglichst einfach umsetzten kann mit dem Packet-schicken :?:

lg, Alleinherrscher :P
r4id3n
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 115

Win XP Home, Win XP Pro
D6 Prof, D7 Ent, K3 Ent
BeitragVerfasst: Mo 22.11.04 15:59 
Der ReadBuffer-Methode kannst du angeben, wie viel du lesen möchtest....
Frag mich nicht nach der syntax, die steht in der Hilfe ;-)
Ebenso kannst du mit WriteBuffer eine bestimmte anzahl an Zeichen schreiben (length gibt dir die länge des strings)

Hoffe das hat geholfen!
alleinherrscher Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mo 22.11.04 19:34 
Titel: Hä, wie jetzt?
Hmmm, also da ich mich so gar nicht mit den indy komponenten auskenne, hab ich mir jetzt diesen Code "gebastelt", der -natürlich- nicht funktioniert...

ausblenden volle Höhe Delphi-Quelltext
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:
//Files senden

Idtcpclient1.writeln('~fsm'+opendialog1.filename);
memo1.lines.add('Trying to send File '+filename1 + ' to the remote computer');

  with IdTCPClient1 do
  begin
        fs := TFileStream.Create(filename1, fmOpenRead); //Datei in FileStream einlesen
        iTmpSize  := 0;
        tmpMS := TMemoryStream.Create;
        iFileSize := fs.Size;
        fs.Position := 0;
        while iTmpSize<iFileSize do begin
             tmpMs.clear;
             Application.ProcessMessages;
             iNextSize := iFileSize - iTmpSize;
             if iNextSize > packagesize then
                iNextSize := packagesize;
             iTmpSize := iTmpSize + tmpMs.CopyFrom(fs,iNextSize);
        try
             OpenWriteBuffer; //stellt sicher, dass alle Daten versendet werden
             WriteStream(tmpms, true, true,0); {das 2. true ist wichtig!, da es bewirkt, dass die Größe des Streams mittels WriteInteger zuerst verschickt wird}
             CloseWriteBuffer;
        except
             CancelWriteBuffer;
        end;

  end;

      fs.free;
      FreeAndNil(tmpMs);
      sendscreenshot:=False;
      memo1.lines.add('Transfer done!');

end;


 end;


ausblenden volle Höhe Delphi-Quelltext
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:
//FILES EMPFANGEN
iReceivedBytes := 0;
fs := TFileStream.Create('C:\filestream.tmp', fmCreate or fmShareExclusive);




 with AThread.Connection do


   While (not AThread.Terminated) and (AThread.Connection.Connected)
      do begin
       tmpMS.clear;

            SizeOfIncomingStream := ReadInteger; //Größe des Streams empfangen
       try
      ReadStream(tmpMS, SizeOfIncomingStream); //und übergeben
        if tmpMS.Size > 0 then begin
          fs.copyFrom(tmpMS,0);

          iReceivedBytes := iReceivedBytes + tmpMS.Size;
        end;
      except
      showmessage('fehler!');
      end;
   end;
         fs.Free;
      streamsend:=False;
      AThread.Connection.Disconnect;
      
    AThread.Synchronize(weitergehts);



exit;
end;

AThread.connection.disconnect;
AThread.Synchronize(weitere_bearbeitung);
exit;



Delphi gibt hier leider ne fehlermeldung zurück, die sehr wenig aussagefähig ist...wie das nun mal bei indy so ist...

Ne idee, was falsch ist, oder vielleicht sogar nen bessere lösung?

Sorry, dass ich gerade meine Programme von euch "Debuggen" lasse, aber wie gesagt, ich hab keine peilung von indy...delphi is eigentlich kein problem, aber zu indy habe ich noch nicht mal irgendeine anständige hilfedatei...

Liebe Grüße, Alleinherrscher :shock:
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Mo 22.11.04 20:47 
Hallo alleinherscher (ich hoffe dein Name ist nicht ernst gemeint ;)),

ich weiss zwar nicht, welche Aufgabe dein Programm außer dem Kopiervorgang noch zur Verfügung stellt, aber ich würde grunsätzlich alle Dinge, die du zwischen zwei Programm kennzeichnen, z.B. durch einen einfach "Kopf" (Header):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
const
  diSFileCopyStart = 1;
  diSFileCopyEnd = 2;
  diSFileCopyPart = 3;
  diEFileCopyAbort = 4;

  diEFileCopyGetPart = 13;
  diEFileCopyAbort = 14;

  diChat = 20;
  //usw...

TDataHeader = record
  Id: Byte; //Für die Indentifikation;
  Pos: Cardinal; //Für Position beim Kopieren
  Data: Pointer; //Für den Inhalt
Wenn du nun eine Datei verschicken möchtest, dann solltest du, wie schon vorher vorgeschlage, die Datei in einzelne Stücke "zerlegen" und dann Stück für Stück übertragen. Das hat zum einen den Vorteil, dass du verlorengegangene Teilstücke einfach erneut schicken kannst und die Übertragen eventuell auch schneller geht, zumindest ist sie sicherer.
Wie du nun den Übertragungsvorgang vornimmst, das bleibt alleine dir überlassen. Ich möchte dir nur ein paar Tipps geben, die Übertragen vor Störungen schützen. Pseudoquelltext für die Übertragung:
ausblenden Delphi-Quelltext
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:
//S: Steht für Sender, E: für Empfänger
//Senden-Funktion sieht wie folgt aus:
  procedure Senden(Id1: Byte; Pos: Cardinal; var Data);

//S: Copyvorgang starten:
  Senden(diSFileCopyStart);
//E: Antwort
  //Ja:
  Senden(diEFileCopyGetPart, 0); //0 = Anfang
  Datei zum speichern öffnen (TFileStream)
  //Nein:
  Senden(diEFileCopyAbort);

//S: Wenn ja, Vorgang starten
  Datei öffnen (TFileStream);
  //Zur Position 0 wechseln
  Erster Block einlessen (Größe: 1024 * x)
  Senden(diSFileCopyPart, Größe des Blockes, Block);
//E:
  Block speichern (TfileStream)
  Senden(diEFileCopyGetPart, Stream.Pos);  //Neue Position senden

//S:
  Zur Position P wechseln
  Block einlessen
  Senden(diSFileCopyPart, Größe des Blockes, Block);

//E: Siehe oben bis die Nachricht diSFileCopyEnd oder diSFileCopyAbort kommt
//Am ende noch Dateien schliessen und fertig.
So, jetzt bleibt es dir überlassen, diesen Pseudoquelltext in Quelltext um zusetzen. Indy bietet die Methode WriteBuffer und ReadBuffer (oder ähnliche), mit denen du die Aufgaben erfüllen kannst.

Viel Glück und wenn du Probleme hast, dann frag wieder!

Grüße,
Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.