Delphi-PRAXiS
Seite 3 von 5     123 45      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Dateiaustausch zwischen clientsocket und serversocket..^^ (https://www.delphipraxis.net/100996-dateiaustausch-zwischen-clientsocket-und-serversocket-%5E%5E.html)

Apollonius 8. Okt 2007 16:57

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
Nein, nimm nicht SizeOf, da kommt sowieso immer vier raus. Nimm Stream.Size.

cRayZo 8. Okt 2007 17:11

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
okay
Delphi-Quellcode:
var size:integer;
(...etc)
bitmap.SaveToStream(Stream);
size:=stream.Size;
(senden...etc)
wenn ich die Länge vorher aber in einem Sendtext übertrage, gehts ja nicht, weil
Zitat:

Zitat von ---> Muetze1
Wenn du noch nicht fertig alles empfangen hast, dann würdest du mit ReceiveText sogar die Daten als string bekommen...

soll ich die länge des streams also in den stream selbst, an den Anfang setzen oder wie. Stell ich mir schwer umsetzbar vor

Apollonius 8. Okt 2007 17:27

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
Du sendest auf Serverseite erstmal die Größe mit SendBuf und dann den eigentlichen Stream mit SendStream. Auf der Clientseite prüfst du, ob die Übertragung schon begonnen hat - wenn nein, dann liest du die Größe und speicherst sie global. Andernfalls liest du mit deiner eigenen Methode (Puffer allozieren, lesen und in den Stream speichern) die Daten aus und prüfst, ob du die Gesamtgröße schon erreicht hast.

Jens Schumann 8. Okt 2007 17:29

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
Hallo,
ich habe das Gefühl das hier mit "nicht blockierenden Socktes" gearbeitet wird.
Ich empfehle Dir die Komponenten in den "blockierenden Modus" zu schalten und die Übertragung
mit TWinSocketStream zu realisieren. Dann lösen sich alle hier genannten Probleme in Luft auf.
Die speicherst alles was Du Üertragen möchtest in einen Stream der dann mit TWinSocketStream gesendet wird.
Das Bitmap könntest Du dann mit TBitmap.SaveToStream(aWinSocketStream) senden.

Für die serverseitige ClientExecute Methode gibt es sogar ein Beispiel in der OH.

Muetze1 8. Okt 2007 17:56

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
Zitat:

Zitat von cRayZo
also kann ich im server, wenn ich das Bild komplett geladen habe (sprich nach dem screenshot) einen sizeof machen? das müsste doch noch gehen oder?

SizeOf() liefert die Grösse eines Typs/Variable, welchen diese belegt im Speicher. Eine Instanz ist intern ein Pointer... bla blubb, siehe oben ... und liefert von daher immer 4 - weil 4 Bytes ist ein Pointer auf einem 32 Bit System/Compiler gross. (auch hier: siehe zuvor).

Stream.Size ist schon die richtige Antwort von Apollonius. Und zu deinem Problem mit dem SendText: Sende die Grösse einfach nicht in Textform (also als String) sondern als Binäre Daten. Dann ersparst du dir einfach das Umwandeln in den String und zurück und vor allem: du hast eine definierte Länge. Die Grösse eines LongInt/Int64/Char/Byte etc sind immer gleich gross bei dem gleichen Compiler und Zielsystem, weil sonst könnte der Compiler schlecht beim Erstellen des Programmes den Speicherplatz für Variablen vorhalten. Von daher wäre das eine gute Lösung.

Soviel zur Theorie, nun zum Code: Die Grösse dieser Variablen bzw. des Typs ermittelst du - tada - mit SizeOf(). Dieses würde dir z.B. für LongInt 4 Bytes liefern und für Int64 sogar 8 Bytes. Damit hättest du die Gewissheit, dass du immer nur (bei Nutzung eines LongInt's) 4 Bytes vorne die Grösse sind und alles nachfolgende schon die Stream-Daten.

Delphi-Quellcode:
var
  lLen: LongInt;
begin
  ...
  // Bitmap sichern in Stream, etc
  ...
  lLen := Stream.Size
  Socket.SendBuf(lLen, SizeOf(lLen));
  Socket.SendStream(Stream);
end;
Auf der Gegenseite einfach die Länge auslesen und dann damit arbeiten. Und damit du z.B. unterscheiden kannst, ob du nun das erste Mal versuchst Daten zu lesen und somit erstmal die 4 Bytes Streamgrösse auslesen musst oder ob es schon Stream-Daten sind, kannst du dich ja an deinem Empfangsstream orientieren: ist er schon angelegt, dann weisst du um die Länge, wenn nicht, dann erstmal diese auslesen...

Und das mit dem Empfangen der Länge solltest du mit dem Codeschnipsel gut selbst hinbekommen.

@other: Ja, ich hätte auch alles einfach mit Integer erklären können, aber ich bezog mich darauf, dass die Datentypen bei den gleichen Compilern und Zielsystemen gleich gross sind. Leider wächst aber Integer (generischer Ganzzahl-Typ) mit und wird bei einem 64-Bit Compiler (Delphi "Commodore", Winter 2008) auch 64 Bit gross sein, von daher wollte ich diesen Fakt nicht auswälzen und habe LongInt genommen, weil das definitiv 32 Bit gross bleibt.

cRayZo 10. Okt 2007 17:38

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
okay, wieder scheiterts am Vokabular
ich hab mir versucht irgendwie trotzdem zu helfen :lol:
(trau mich ja fast ned das zu posten :? )

hier für den empfänger (Client)
Delphi-Quellcode:
begin
  iLen := Socket.ReceiveLength;
  GetMem(Bfr, iLen);
  try
    Socket.ReceiveBuf(Bfr^, iLen);
    FStream.Write(Bfr^, iLen);

    if FileExists('c:\teststream.bmp')
    then       begin
                if x=Fstream.Size
                then image1.Picture.Bitmap.LoadFromStream(Fstream)end
    else begin x:=strtoint(copy(inttostr(Socket.ReceiveBuf(Bfr^, iLen)),0,4)); // * weiter unten -->
    FStream := TFileStream.Create('c:\teststream.bmp', fmCreate or fmShareDenyWrite); end;
  finally
    FreeMem(Bfr);
  end;

//*bestimmt viel leichter^^ aber ich kenn nur copy und copy geht nunmal soweit ich weiß nur mit string^^
end;
kanns Programm übrigens ohne Fehler starten, aber beim sendeversuch kommt ein Fehler.. (iwie auch klar)

Muetze1 10. Okt 2007 19:10

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
Ok, dann doch mal der Code beim Client:

1. Eine Variable vom Typ TStream im private Abschnitt der Form deklarieren (für die Daten) und dazu eine Variable vom Typ Integer, welche die Grösse der Daten hält.
Delphi-Quellcode:
  xxx = class(TForm)
  ...

  private
    FStream: TStream;
    fStreamDataSize: Integer;
  ...
  end;
2. Empfangsroutine: OnClientRead
Delphi-Quellcode:
procedure xxx.ClientSocket1ClientRead(...)
var
  iLen: Integer;
  Bfr: Pointer;
begin
  if not assigned(FStream) then // noch keine Übertragung bisher, Stream ist nil
  begin
      // Ok, dann müssten wir erstmal schauen und die Grösse des folgenden Streams
      // auslesen. Dazu erstmal schauen, ob wir die Grösse bisher überhaupt komplett empfangen haben...
    if Socket.ReceiveLength >= SizeOf(fStreamDataSize) then
    begin
        // dann nun die Grösse einlesen
      Socket.ReceiveBuf(fStreamDataSize, SizeOf(fStreamDataSize));

        // dann Stream anlegen
      FStream := TMemoryStream.Create;
    end;
//    else
//      Exit; // ok, dann weiter warten, bis wir die Grösse komplett empfangen haben (Code unnötig)
  end;

    // ok, hier nun, wenn der Stream existiert, einlesen der Daten die empfangen wurden und Schreiben in den Stream
  if assigned(FStream) then
  begin
    iLen := Socket.ReceiveLength;

      // Ok, nur die Daten auch empfangen, die zu unserem Stream gehören. Also schauen wieviel wir noch vom Stream einlesen
      // müssen...
    iLen := Min(fStreamDataSize, iLen);

    GetMem(Bfr, iLen);
    try
      Socket.ReceiveBuf(Bfr^, iLen);

//      fStreamDataSize := fStreamDataSize - FStream.Write(Bfr^, iLen); // beides gleich - schreiben der Daten
      Dec(fStreamDataSize, FStream.Write(Bfr^, iLen);                   // und Variable fStreamDataSize runterzählen um die
                                                                         // empfangenen und geschriebenen Daten...
    finally
      FreeMem(Bfr);
    end;

    if fStreamDataSize = 0 then // alles empfangen?
    begin
        // Positionszeiger zurücksetzen
      FStream.Position := 0;

        // Image einlesen
      Image1.Picture.Bitmap.LoadFromStream(FStream);
   
        // MemoryStream freigeben und auf nil setzen (wegen den If Assigned() Abfragen)
      FreeAndNil(FStream);
    end;
  end;

    // wenn er hier ankommt und ReceiveLength() ist immernoch > 0, dann sind noch Daten im Stream, die aber nicht
    // mehr zum Bild gehören - oder - wir haben die Grösse der Streamdaten noch nicht empfangen.
end;
3. Beim Server folgendes um die Grösse vorne weg zu senden:
Delphi-Quellcode:
var
  lLen: Integer;
  lStream: TStream;
begin
  lStream := TFileStream.Create('c:\testbild.bmp', fmOpenRead);

  lLen := lStream.Size; // grösse Stream ermitteln
  Socket.SendBuf(lLen, SizeOf(lLen)); // Grösse senden

  Socket.SendStream(lStream); // dann das Bild hinten dran...
end;
So, soweit zur Theorie. Alles hier im Forumfenster geschrieben, sollte aber so laufen...

cRayZo 10. Okt 2007 19:17

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
jo ist gebongt und jetzt?.. :?:

Muetze1 10. Okt 2007 19:27

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
Zitat:

Zitat von cRayZo
jo ist gebongt und jetzt?.. :?:

Sorry, war noch beim tippen - hatte mich nur verdrückt mit ALT-S anstatt ALT-D...

cRayZo 10. Okt 2007 19:48

Re: Dateiaustausch zwischen clientsocket und serversocket..^
 
achso, kein Problem, ja vielen Dank auf jeden fall!!!
einmal nur ne klammer vergessen(is ja np ;) )
mein delphi gibt den Ausdruck 'min' nur als nicht definiert zurück.
Delphi-Quellcode:
iLen := Min(fStreamDataSize, iLen);
das versteh ich aber nicht, ist doch eine Funktion


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:00 Uhr.
Seite 3 von 5     123 45      

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