Dateiaustausch zwischen clientsocket und serversocket..^^
(kurz vornweg, ja gesucht hab ich schon!)
Hi, wie kann ich eine beliebige Datei zwischen client und Server hin und herschicken? Ich habe mir schon lange gedanken gemacht, aber ich komm einfach nciht auf die Lösung. Die suche hat mir auch nicht viel gebracht, da vieles mit indy erklärt wird. Soweit ich das aber verstanden habe, is das erst ab Delphi 7 verfügbar.. könnt ihr mir weiterhelfen? ich muss doch nur eine atei übertragen... ^^ thx schonmal :) PS: Texte zu verschicken klappt problemlos. Ich weiß auch schon dass ich 'sendstream' nehmen sollte. Aber wie soll ich das mit sendstream verwirklichen? |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Diesen Thread hast Du aber schon gesehen, oder?
|
Re: Dateiaustausch zwischen clientsocket und serversocket..^
wo genau ist dein problem? Ein Text ist auch nur eine ansamlung von Bytes. Genau wie eine Datei. Du kannst also eine Datei genau so versenden wie einen Text (vorrausgesetzt ich vermute dein Problem an der richtigen Stelle des Vorhabens). Vielleicht solltest du mal zeigen was du schon hast und wo es genau hängt.
|
Re: Dateiaustausch zwischen clientsocket und serversocket..^
also hier meine "produktion" hüstel
ich hab mit type gearbeitet, ich weiß dass man das eig. nicht macht, aber ich hab iwie alles schon ausprobiert, und dann eben auch das.. naja Client onklick
Delphi-Quellcode:
Server onread
type
testrecord=record var screen:TBitmap; begin Varscreen: TBitmap; sendscreen:Testrecord; with sendscreen do begin screen:=Varscreen; end; Clientsocket1.Socket.SendBuf(Varscreen,SizeOf(Sendscreen));
Delphi-Quellcode:
var
receivetext: string; screnVar:TBitmap; incomScreen:testRecord; begin QueryMemo.Lines.Add(DateTimeToStr(Now)+' Uhr: Bild wird geladen'); socket.receivebuf(incomScreen, SizeOf(incomScreen)) ; with incomScreen do begin screnVar:=screen; end; // Image1.Picture.Assign(screnvar); image1.Picture.Bitmap:=screnVar; QueryMemo.Lines.Add(DateTimeToStr(Now)+' Uhr: Bild erhalten'); except showmessage('x'); end; |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
TBitmap ist eine Klasse und diese sind intern nur Zeiger. Wenn du nun ein TBitmap versendest, dann sendest du nur die Adresse im Speicherbereich deiner Applikation, wo das Objekt liegt. Somit: Keine Daten und nichts. Der Empfänger kann damit nichts anfangen, da an der angegebenen Adresse in seinem Speicherbereich was ganz anderes liegt.
Vorschlag: schau dir mal in der Hilfe folgendes an und ich denke mal, du kommst auf die Idee, welche ich dir hier schmackhaft machen will: TMemoryStream, TBitmap.SaveToStream, TCustomWinSocket.SendStream |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
also dann sowas in der art oder wie?
(hier jetzt einfach mal am beispiel von einem Screenshot, den muss man nicht aus ner datei laden) Client
Delphi-Quellcode:
Server
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket); var Stream : TMemoryStream; begin Stream := TMemoryStream.Create; clientsocket1.Socket.ReceiveBuf(stream,sizeof(stream)); image1.Picture.Bitmap.LoadFromStream(stream); end; procedure TForm1.Button1Click(Sender: TObject); begin ClientSocket1.Port := 270; //Festlegung des Ports ClientSocket1.Host := '127.0.0.1'; //IP des Zielrechners ClientSocket1.active := true; //Aufbau der Verbindung end;
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin ServerSocket1.Port := 270; //Festlegung des Ports ServerSocket1.active := true; //Aktivierung der ServerSocket end; {procedure MakeScreenShot(const ATarget: TBitmap); var DesktopDC: HDC; begin DesktopDC := CreateDC('DISPLAY', nil, nil, nil); try ATarget.PixelFormat := pfDevice; ATarget.Width := Screen.Width; ATarget.Height := Screen.Height; BitBlt(ATarget.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DesktopDC, 0, 0, SRCCOPY); finally DeleteDC(DesktopDC); end; end;} <--irrelevant procedure TForm1.Button1Click(Sender: TObject); var Stream : TMemoryStream; bitmap:Tbitmap; begin Stream := TMemoryStream.Create; MakeScreenShot(bitmap); bitmap.SaveToStream(Stream); Stream.Position := 0; Stream.Free; Serversocket1.Socket.Connections[0].SendStream(Stream); end; |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Zitat:
Delphi-Quellcode:
Das wird zu Problemen führen, weil die OnClientRead() Funktion mehrfach aufgerufen wird (werden kann), bis du die gesamten Daten empfangen hast. Somit musst du den Memorystream woanders erzeugen (so das du wirklich nur eine Instanz davon hast) und damit du mit jedem OnClientRead die neu empfangenen Teile direkt hinten an den MemoryStream anhängen kannst. Wenn du dann alle Daten empfangen hast, dann kannst du aus dem MemoryStream die Daten auslesen.
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket); var Stream : TMemoryStream; begin Stream := TMemoryStream.Create; clientsocket1.Socket.ReceiveBuf(stream,sizeof(stream)); image1.Picture.Bitmap.LoadFromStream(stream); end; Folgende Fehler in deiner Routine: 1. Du erzeugst jedes mal eine neue Instanz von TMemoryStream - du brauchst nur eine 2. Du gibst die Instanz bei ReceiveBuf() an, aber der will einen Zwischenpuffer haben. Du kannst die Instanz niemals bei dieser Funktion direkt angeben. 3. Instanzen sind intern nur Zeiger auf das Objekt im Speicher - siehe mein Beitrag zuvor. Was für das Senden gilt, gilt hier genauso für das Empfangen, schliesslich sind es jedesmal Instanzen. 4. Nach dem Schreiben von Daten in den Stream, wird der Dateizeiger (TStream.Position) auch um die jeweilige Byteanzahl weiter gesetzt und LoadFromStream() liest aber der aktuellen Dateiposition. Damit würde LoadFromStream() immer fehlschlagen, da er immer am Ende der Daten steht. 5. Du gibst nirgendwo den Stream wieder frei.
Delphi-Quellcode:
1. Wenn du den Stream mit .Free wieder freigibst (und er somit weg ist), was soll er denn bei dem Aufruf danach noch versenden? Datenmüll? Naja, das macht er bestenfalls sogar.
procedure TForm1.Button1Click(Sender: TObject);
var Stream : TMemoryStream; bitmap:Tbitmap; begin Stream := TMemoryStream.Create; MakeScreenShot(bitmap); bitmap.SaveToStream(Stream); Stream.Position := 0; Stream.Free; Serversocket1.Socket.Connections[0].SendStream(Stream); end; 2. Den Stream grundsätzlich nicht freigeben, weil SendStream() übernimmt diesen Part für dich (siehe TCustomWinSocket.SendStream(), da nur SendStream weiss, wann er alles gesendet hat. SendStream macht dies im Hintergrund. 3. Du gibst nirgendwo das Bitmap wieder frei. Am besten mal die Senderoutine aufräumen, da biste wohl am schnellsten bei einer funktionierenden Lösung... |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
okay...^^
also erstmal echtn riesen Dank, dass du dir so viel Mühe gibst, mir das zu erklären! :cheers: (bestimmt nicht leicht xD) Ich versteh auch fast alles. Erstmal zum Server: stimmt das jetzt so (hoff mal schon, denk aber eher nicht^^)
Delphi-Quellcode:
und zum Client nochmal: Dass ichs nicht im onread schreiben darf, leuchtet mir ein, logo! kann nicht klappen. Aber wo soll ich anders (wenn nicht im on read) programmieren, dass das Programm den Stream läd, wenn er doch nicht weiß, wann der stream kommt? (ich hoffe du verstehst was ich meine^^) Und ansonsten sind alle Fehler die ich beim Client gemacht habe durchaus logisch zu verstehen, ich weiß jetzt dass es Fehler sind, und warum, aber ich wüsste nicht, wie ich es anders machen soll (außer Punkt 5^^)
procedure TForm1.Button1Click(Sender: TObject);
var Stream : TMemoryStream; bitmap:Tbitmap; begin Stream := TMemoryStream.Create; MakeScreenShot(bitmap); bitmap.SaveToStream(Stream); Stream.Position := 0; Serversocket1.Socket.Connections[0].SendStream(Stream); bitmap.Free; end; |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Zitat:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var Stream: TMemoryStream; bitmap: TBitmap; begin Stream := TMemoryStream.Create; MakeScreenShot(bitmap); try bitmap.SaveToStream(Stream); finally bitmap.Free; end; Stream.Position := 0; Serversocket1.Socket.Connections[0].SendStream(Stream); end; Zitat:
|
Re: Dateiaustausch zwischen clientsocket und serversocket..^
okay.. also das mit dem "außerhalb von Onread" erstellen müsste dann so gehen oder wie?
Delphi-Quellcode:
und im On read soll dann das stehen?
FStream := TFileStream.Create('c:\temp\test.stream.bmp', fmCreate or fmShareDenyWrite);
end;
Delphi-Quellcode:
das habe ich ich jetzt außerhalb von DP gefunden
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket); var iLen: Integer; Bfr: Pointer; begin iLen := Socket.ReceiveLength; GetMem(Bfr, iLen); try Socket.ReceiveBuf(Bfr^, iLen); FStream.Write(Bfr^, iLen); finally FreeMem(Bfr); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:12 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