AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Dateiaustausch zwischen clientsocket und serversocket..^^
Thema durchsuchen
Ansicht
Themen-Optionen

Dateiaustausch zwischen clientsocket und serversocket..^^

Ein Thema von cRayZo · begonnen am 6. Okt 2007 · letzter Beitrag vom 12. Okt 2007
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    
cRayZo

Registriert seit: 30. Jul 2007
156 Beiträge
 
Delphi 6 Personal
 
#1

Dateiaustausch zwischen clientsocket und serversocket..^^

  Alt 6. Okt 2007, 17:56
(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?
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 17:58
Diesen Thread hast Du aber schon gesehen, oder?
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 17:59
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.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
cRayZo

Registriert seit: 30. Jul 2007
156 Beiträge
 
Delphi 6 Personal
 
#4

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 18:14
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:
type
testrecord=record
var
screen:TBitmap;
begin
Varscreen: TBitmap; sendscreen:Testrecord;

with sendscreen do begin screen:=Varscreen; end;
Clientsocket1.Socket.SendBuf(Varscreen,SizeOf(Sendscreen));
Server onread
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;
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#5

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 18:32
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: Delphi-Referenz durchsuchenTMemoryStream, Delphi-Referenz durchsuchenTBitmap.SaveToStream, Delphi-Referenz durchsuchenTCustomWinSocket.SendStream
  Mit Zitat antworten Zitat
cRayZo

Registriert seit: 30. Jul 2007
156 Beiträge
 
Delphi 6 Personal
 
#6

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 19:12
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:
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;
Server
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;
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#7

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 19:22
Zitat von cRayZo:
also dann sowas in der art oder wie?
Ja, aber ich dachte da nun nur noch an Code, der funktioniert . Aber schauen wir mal, was du gemacht hast...

Delphi-Quellcode:
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;
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.

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 (Delphi-Referenz durchsuchenTStream.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:
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;
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.
2. Den Stream grundsätzlich nicht freigeben, weil SendStream() übernimmt diesen Part für dich (siehe Delphi-Referenz durchsuchenTCustomWinSocket.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...
  Mit Zitat antworten Zitat
cRayZo

Registriert seit: 30. Jul 2007
156 Beiträge
 
Delphi 6 Personal
 
#8

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 19:47
okay...^^
also erstmal echtn riesen Dank, dass du dir so viel Mühe gibst, mir das zu erklären!
(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:
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;
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^^)
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#9

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 20:15
Zitat von cRayZo:
Erstmal zum Server: stimmt das jetzt so (hoff mal schon, denk aber eher nicht^^)
Nö, alles in Ordnung. Vom Code her wird genau das erreicht, aber ein wenig besserer Stil ist es, wenn man Resourcen-Schutzblöcke einführt. Damit kann man, im Falle eines Fehlers, immernoch sicherstellen, dass alle angelegten Resourcen auch wieder freigegeben werden. Und wenn das Versenden und Empfangen klappt, dann können wir nochmal drüber reden über eine kleine Regel die besagt, dass man versuchen sollte Resourcen immer auf der gleichen Ebene anzulegen wie man sie auch freigibt. Und dagegen widerspricht die MakeScreenShot Routine. Aber das machen wir dann ein andermal.

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 von cRayZo:
und zum Client nochmal: Dass ichs nicht im onread schreiben darf, leuchtet mir ein, logo!
Die Aussage ist so nicht richtig. Du kannst sonstwas im OnClientRead machen, aber das Problem ist einfach folgendes: OnClientRead() wird von dem Socket mehrfach aufgerufen, immer dann, wenn er mal wieder einen Teil der Daten empfangen hat. Du musst diese einzelnen Teile zusammenspielen in den MemoryStream. Von daher muss der Stream ausserhalb des OnClientRead Ereignishandlers angelegt werden (einmalig) und im Ereignishandler schreibst du einfach nur den eben empfangenen Datenteil in den Memorystream. Wenn du alle Daten empfangen hast (also alle Bilddaten), dann kannst du den Stream wieder auslesen lassen von einem Image/Bitmap. Und da haben wir schon ein neues Problem: Woher weiss der Empfänger, wieviel Bytes an Daten kommen bis das Bild komplett ist? Immer wenn er im Ereignishandler ist, weiss er ja nicht ob noch mehr Aufrufe kommen oder ob es der letzte war. Auch weiss er nicht, ob die Daten, die er gerade vom Socket ausgelesen hat, komplett für das aktuelle Bild sind oder ob da schon wieder neue Daten mit dranne hängen. Von daher merkt man schon, dass du vorher ein paar Daten noch übertragen musst - z.B. die Länge der Bilddaten. Damit weiss der Client, aja, es kommen ab nun (nach einlesen dieser Informationen) genau 24245 Bytes an Bilddaten. Mit dieser Information kann der Ereignishandler genau sagen: Ok, alle Daten in den Memorystream schreiben und soviel Bytes sind noch zu empfangen oder halt auch: hey, ich habe alles - ich kann das Bild anzeigen! Um diese Informationen zu übertragen kannst du einfach vorher die Grösse der Daten übermitteln und danach die Bilddaten. Im Endeffekt baust du dir damit aber schon ein kleines Protokoll und genau sowas brauchst du hier auch noch. Wenn du hier mal nach Hier im Forum suchenProtokoll suchst, findest du auch schon genug Beiträge von Leuten mit einem gleichen oder ähnlichen Problem, denen wir schon entsprechend geholfen haben. Dort kannst du dir dann sowas leicht mal abschauen.
  Mit Zitat antworten Zitat
cRayZo

Registriert seit: 30. Jul 2007
156 Beiträge
 
Delphi 6 Personal
 
#10

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 6. Okt 2007, 20:36
okay.. also das mit dem "außerhalb von Onread" erstellen müsste dann so gehen oder wie?

Delphi-Quellcode:
FStream := TFileStream.Create('c:\temp\test.stream.bmp', fmCreate or fmShareDenyWrite);
end;
und im On read soll dann das stehen?

Delphi-Quellcode:
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;
das habe ich ich jetzt außerhalb von DP gefunden
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    


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 14:30 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