Re: Dateiaustausch zwischen clientsocket und serversocket..^
Nein, nimm nicht SizeOf, da kommt sowieso immer vier raus. Nimm Stream.Size.
|
Re: Dateiaustausch zwischen clientsocket und serversocket..^
okay
Delphi-Quellcode:
wenn ich die Länge vorher aber in einem Sendtext übertrage, gehts ja nicht, weil
var size:integer;
(...etc) bitmap.SaveToStream(Stream); size:=stream.Size; (senden...etc) Zitat:
|
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.
|
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. |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Zitat:
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:
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...
var
lLen: LongInt; begin ... // Bitmap sichern in Stream, etc ... lLen := Stream.Size Socket.SendBuf(lLen, SizeOf(lLen)); Socket.SendStream(Stream); end; 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. |
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:
kanns Programm übrigens ohne Fehler starten, aber beim sendeversuch kommt ein Fehler.. (iwie auch klar)
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; |
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:
2. Empfangsroutine: OnClientRead
xxx = class(TForm)
... private FStream: TStream; fStreamDataSize: Integer; ... end;
Delphi-Quellcode:
3. Beim Server folgendes um die Grösse vorne weg zu senden:
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;
Delphi-Quellcode:
So, soweit zur Theorie. Alles hier im Forumfenster geschrieben, sollte aber so laufen...
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; |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
jo ist gebongt und jetzt?.. :?:
|
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Zitat:
|
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:
das versteh ich aber nicht, ist doch eine Funktion
iLen := Min(fStreamDataSize, iLen);
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:00 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