Re: Dateiaustausch zwischen clientsocket und serversocket..^
Schau in die Hilfe zu TCanvas.CopyRect() oder auch in die WinAPI zu StretchDraw()
|
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Liste der Anhänge anzeigen (Anzahl: 1)
okay thx
wenn ich eure/deine Nerven noch nicht zu krass strapaziert hab, hätt ich vll noch eine kleine Bitte: Ich hab jetzt die funktionen von Server und Client vertauscht, dann ein paar sachen (aufgrund vom Vertauschen) geändert, und jetzt läuft das nach dem zufallsprinzip... :o mal zeigt er mir ein stark verzerrtes Bild, oder er zeigt mir garnichts, oder es kommt eine Fehlermeldung. ich habe mir mal fStreamDataSize in einem Text ausgeben lassen (der verbleibende Rest an ankommendem Stream) dieser ist nie null (bis auf das eine Bild (anhang), das ich eher als Kunstwerk als einen screenshot identifizieren würde). meine Bitte: vll nur nochmal über den code drüberfliegen und sagen was da noch falsch ist, den Code hab ich ja ansonsten (fast) verstanden, schonmal thx. Client (sender)
Delphi-Quellcode:
Server (empfänger)
var
bitmap:Tbitmap;size:integer;lLen: Integer;lStream: TStream; begin lStream := TMemoryStream.Create; bitmap:=TBitmap.create; MakeScreenShot(bitmap); bitmap.SaveToStream(lStream); size:=lstream.Size; lStream.Position := 0; lLen := lStream.Size; Clientsocket1.Socket.SendBuf(lLen, SizeOf(lLen)); Clientsocket1.Socket.SendStream(lStream); bitmap.Free; end;
Delphi-Quellcode:
uses (...)Math (..)
(..) private FStream: TStream; fStreamDataSize: Integer (..) //onreceive Var iLen: Integer; Bfr: Pointer; begin if Globvarmess=8 then begin //Globvarmess wird beim senden des Befehls an den CLient auf 8 gesetzt. //Damit er zwischen den versch. ankommend. Nachrichten unterscheiden kann if not assigned(FStream) then begin if ServerSocket1.Socket.Connections[0].ReceiveLength >= SizeOf(fStreamDataSize) then begin ServerSocket1.Socket.Connections[0].ReceiveBuf(fStreamDataSize, SizeOf(fStreamDataSize)); FStream := TMemoryStream.Create; end; // else // Exit; end; if assigned(FStream) then begin iLen := ServerSocket1.Socket.Connections[0].ReceiveLength; iLen := min(fStreamDataSize, iLen); GetMem(Bfr, iLen); try ServerSocket1.Socket.Connections[0].ReceiveBuf(Bfr^, iLen); // fStreamDataSize := fStreamDataSize - FStream.Write(Bfr^, iLen); Dec(fStreamDataSize, FStream.Write(Bfr^, iLen)); finally FreeMem(Bfr); end; label13.Caption:=inttostr(fStreamDataSize); if fStreamDataSize = 0 then // alles empfangen? //ab hier benutzt er den Code nicht mehr Label13 ist (fast) nie x2, x2 etc begin Label13.Caption:='x2'; FStream.Position := 0; Label13.Caption:='x3'; Image1.Picture.Bitmap.LoadFromStream(FStream); Label13.Caption:='x4'; FreeAndNil(FStream); Label13.Caption:='x5'; end; end; end; |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Client:
1. Wozu ist size definiert? Du solltest dazu auch eine entsprechenden Hinweis von Compiler bekommen. 2. Warum nutzt du ClientSocket1.Socket anstatt den übergebenen Socket? 3. Resourcenschutzblock für's Bitmap? Server: 1. Warum nutzt du nicht das übergebene Socket anstatt fest auf die erste Verbindung des Servers zu zu greifen? 2. Wenn es jemals mehr als eine Verbindung beim Client sein sollten, dann musst du daran denken, dass du entsprechend auch soviele FStream und fStreamDataSize Variablen brauchst. 3. Sicher das dein anderer Code für die Befehle dazwischenspielt? Wie sollte sonst der GlobalVarMess verändert werden? Kannst du dies 100%ig ausschliessen? Schliesslich entfernt ein ReceiveText() alle im Puffer befindlichen Daten - auch wenn du nachher nur 5 Zeichen brauchtest. Hast du dies beachtet? 4. Wenn fStreamDataSize niemals 0 wird, dann entfernst du mit anderen Code Daten aus den Sockets welche empfangen wurden. Damit kann das Bild niemals komplett empfangen werden. Wie sieht denn der vorenthaltene Code beim Empfänger (Server) im OnClientRead() aus? /EDIT: Ich habe dir ein Auto verkauft - wenn du daraus ein LKW baust, dann verlierst du die Garantie. Somit musst du selber wissen was du machst. Reparieren kann ich's gerne, aber das kostet wie in jeder anderen Werkstatt Geld... |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
aaaalso, hier der komplette text:
Server
Delphi-Quellcode:
Client
procedure TForm1.Button1Click(Sender: TObject);
begin globvarmess:=1; {1} QueryMemo.Lines.Add(DateTimeToStr(Now)+ ' Uhr:out--> //networkscan'); {2} QueryMemo.SelStart :=lengthqueryvar; // Startposition der Markierung {3} QueryMemo.SelLength := 24 ; // Ende der Markierung {4} QueryMemo.SelAttributes.Style := [fsbold]; // Markierung fett drucken {5} QueryMemo.SelLength := 0; // Markierung beenden {6} lengthQueryVar:=Length(Querymemo.Text); Serversocket1.Socket.Connections[0].SendText('//networkscan'); end; procedure TForm1.Button2Click(Sender: TObject); var iLen: Integer; Bfr: Pointer; begin globvarmess:=2; serversocket1.Socket.Connections[0].SendText('//screen'); end; procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); begin if Globvarmess=1 then begin Richedit2.Text:=Receivetext;Richedit2.Text:=Copy(Richedit2.Text,6,length(Richedit2.Text)) ;Listboxnetscan.Items:=Richedit2.Lines end; if Copy(ReceiveText,1,3)='inc' then begin QueryMemo.Lines.Add(DateTimeToStr(Now)+' Uhr:'+ReceiveText); {2} QueryMemo.SelStart :=lengthqueryvar; // Startposition der Markierung {3} QueryMemo.SelLength := 24 ; // Ende der Markierung {4} QueryMemo.SelAttributes.Style := [fsbold]; // Markierung fett drucken {5} QueryMemo.SelLength := 0; // Markierung beenden {6} lengthQueryVar:=Length(Querymemo.Text); end else if Globvarmess=2 then 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 ServerSocket1.Socket.Connections[0].ReceiveLength >= SizeOf(fStreamDataSize) then begin // dann nun die Grösse einlesen ServerSocket1.Socket.Connections[0].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 := ServerSocket1.Socket.Connections[0].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 ServerSocket1.Socket.Connections[0].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; label13.Caption:=inttostr(fStreamDataSize); if fStreamDataSize = 0 then // alles empfangen? begin Label13.Caption:='x2'; // Positionszeiger zurücksetzen FStream.Position := 0; Label13.Caption:='x3'; // Image einlesen Image1.Picture.Bitmap.LoadFromStream(FStream); Label13.Caption:='x4'; // MemoryStream freigeben und auf nil setzen (wegen den If Assigned() Abfragen) FreeAndNil(FStream); Label13.Caption:='x5'; 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; end;
Delphi-Quellcode:
receivetext:=socket.Receivetext;
if Receivetext='//networkscan' then begin Richedit1.Text:=''; try ScanNetworkResources(RESOURCETYPE_DISK, RESOURCEDISPLAYTYPE_SERVER, Richedit1.Lines); except Clientsocket1.Socket.SendText('inc: Fehler beim Auslesen der Netzwerkgeräte'); end; Clientsocket1.Socket.Sendtext('mess:'+Richedit1.Text) end else if ReceiveText='//screen' then begin lStream := TMemoryStream.Create; bitmap:=TBitmap.create; MakeScreenShot(bitmap); bitmap.SaveToStream(lStream); size:=lstream.Size; lStream.Position := 0; //lStream := TFileStream.Create('c:\testbild.bmp', fmOpenRead); lLen := lStream.Size; // grösse Stream ermitteln Clientsocket1.Socket.SendBuf(lLen, SizeOf(lLen)); // Grösse senden Clientsocket1.Socket.SendStream(lStream); bitmap.Free; end else Clientsocket1.Socket.SendText('inc: unbekannter Befehl'); |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Wenn du mehr als nur ein Bild übertragen willst, dann musst du ein entsprechendes Protokoll dir ausdenken um Daten und Anweisungen ordentlich auseinander halten zu können. Ich hatte dir vorhin schon geschrieben, dass ReceiveText den komplett empfangenen Buffer ausliest und als String zurück gibt. Was machst du? Du rufst ReceiveText einfach auf im OnClientRead - ohne ab zu prüfen ob du vllt. gerade bei der Bildübertragung bist - nein - einfach die Bytes rausholen und gut ist. Warum auch - ist doch egal, das andere klappt schon.
Delphi-Quellcode:
Vor allem das witzige ist ja: wenn du da vllt. einen ein kilometerlangen String im Socket hast, dann bekommst du ihn mit diesem einen Aufruf zurück geliefert und dann ist der Socket leer. Ist schön das du davon nur 3 Zeichen abschneidest und den Rest wegwirfst. Wozu sendest du überhaupt soviel?
if Copy(ReceiveText,1,3)='inc' then begin
Wie schon zuvor in diesem Thread hier erklärt: Der Socket hat kein Protokoll und überträgt rein die Daten. Wenn du auf der einen Seite einen String mit einem SendText() reinwirfst, dann kommt er auf der anderen Seite (im schlechtesten Falle) in einzelnen Buchstaben an. D.h. dein OnClientRead wird so oft aufgerufen mit ReceiveLength = 1 wie der String Buchstaben hat, und du bekommst auch immer nur ein Buchstabe. Von daher musst du dich organisieren. Du musst wissen, was da nun im Socket drinne steht und wie du das zu handeln hast. Der Socket macht nichts weiter als die Daten zu übertragen, dabei ist es ihm völlig egal, was er dort überträgt und wie du denkst, das es zusammen gehört. Alles was du auf der einen Seite reinstopfst, kommt auch auf der anderen Seite irgendwann wieder aus. Die Reihenfolge wird stimmen, aber es kann ganz frei geteilt rauskommen. Das zusammenpuzzlen und entsprechen interpretieren ist deine Sache. Du kannst grundsätzlich nicht einfach Text und Binärdaten mischen, so lange du nicht genau weisst: Nun ist das jeweilige im Socket enthalten bzw. es ist so lang. Zitat:
|
Re: Dateiaustausch zwischen clientsocket und serversocket..^
"Ist schön das du davon nur 3 Zeichen abschneidest und den Rest wegwirfst. Wozu sendest du überhaupt soviel?
Ich sende nicht mehr, als ich brauche! die ersten drei ziffern werden nur zum überprüfen benutzt. halt mich bitte nicht für allzu dumm, bloß weil ich mich mit server/Client nicht so gut auskenne... Jeder Befehl, jede nachricht, die ausgetauscht wird, hat ein Präfix oder ist dur die globale message variable definiert. Wenn ein "Inc:" am anfang steht, übernimmt er einfach den ankommenden Text und schreib ihn mit line add und Zeit in ein Richedit,
Delphi-Quellcode:
ich hatte vor das weiter auszubauen und präfixe wie "mess" etc einzubinden, die jeweils anderes bewirken. Wenn zum Beispiel eine message einkommt schreibt er den einkommenden text in eine showmessage, bei incoming in ein trichedit und wenn eine globale message variable definiert ist, liest er den ankommenden Text je nach definition aus. Seis ein Bild, seis eine Datei oder seis ein andersweitig verwendeter Text!
{1} QueryMemo.Lines.Add(DateTimeToStr(Now)+ ' Uhr:out--> ' + einkommende Nachricht'); <--
{2} QueryMemo.SelStart :=lengthqueryvar; {3} QueryMemo.SelLength := 24 ; //hier wird nur die uhrzeitdicker gedruckt für mehr übersicht. {4} QueryMemo.SelAttributes.Style := [fsbold]; {5} QueryMemo.SelLength := 0; {6} lengthQueryVar:=Length(Querymemo.Text); "Nun such eine Werkstatt oder mach es nochmal - dann aber mit viel mehr Vorsicht und Wissen darum! " mach ich auch, der Code war eig eher auf client/server- lernen und vertrautmachen ausgelegt, hatte damit vorher noch nie gearbeitet. Ich hatte ihn nicht auf etwas größeres ausgelegt. |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Entschuldige wenn es etwas harsch war, aber ich hatte beim Beitrag zuvor schon darauf hingewiesen und vermutet, dass ReceiveText aufgerufen wird. Und dann postest du einen Code der dies bei jedem Aufruf von OnClientRead aufruft. Es ist fast schon ein Wunder, dass er überhaupt soweit kommt irgendwas in den Stream zu schreiben...
Zitat:
Ich hoffe es war nun verständlich was du mit dem ReceiveText anrichtest. Und nun stell dir mal vor, dass der Server gar keinen Text geschickt hatte sondern noch die Bilddaten übertragt. Dein ReceiveText Aufruf holt alle bisher empfangenen Daten aus dem Puffer des Sockets. Damit bekommst du einen String mit binären Bilddaten - die dann ReceiveBuf() nicht mehr bekommt, da du schon alles rausgeholt hast. Somit: du zerstückelst das Bild. Deshalb: du musst immer wissen was wann über den Socket übertragen wird und wozu es gehört. Dazu ist es nötig die Übertragungen und Daten zu ordnen und dafür brauchst du ein Protokoll. |
Re: Dateiaustausch zwischen clientsocket und serversocket..^
Auch wenn es zuvor vielleicht recht harsch war: Wie siehts aus? Wie ist der Stand?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:35 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