AGB  ·  Datenschutz  ·  Impressum  







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

Dateiaustausch zwischen clientsocket und serversocket..^^

Ein Thema von cRayZo · begonnen am 6. Okt 2007 · letzter Beitrag vom 12. Okt 2007
Antwort Antwort
Seite 5 von 5   « Erste     345
Muetze1
(Gast)

n/a Beiträge
 
#41

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 11. Okt 2007, 16:01
Schau in die Hilfe zu Delphi-Referenz durchsuchenTCanvas.CopyRect() oder auch in die WinAPI zu MSDN-Library durchsuchenStretchDraw()
  Mit Zitat antworten Zitat
cRayZo

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

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 11. Okt 2007, 17:29
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...
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:
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;
Server (empfänger)
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;
Miniaturansicht angehängter Grafiken
projekt1_108.jpg  
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#43

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 11. Okt 2007, 18:19
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...
  Mit Zitat antworten Zitat
cRayZo

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

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 11. Okt 2007, 20:07
aaaalso, hier der komplette text:


Server
Delphi-Quellcode:
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)='incthen 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;
Client
Delphi-Quellcode:
receivetext:=socket.Receivetext;
if Receivetext='//networkscanthen 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='//screenthen 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');
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#45

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 11. Okt 2007, 20:19
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.

if Copy(ReceiveText,1,3)='incthen begin 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?

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 von Muetze1:
/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...
Wie geschrieben. Du hast es zum LKW umgebaut - und warst nicht vorsichtig genug bzw. hast dich nicht kundig gemacht und bist somit ohne richtiges Wissen über den Code zu Werke gegangen. Nun such eine Werkstatt oder mach es nochmal - dann aber mit viel mehr Vorsicht und Wissen darum!
  Mit Zitat antworten Zitat
cRayZo

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

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 11. Okt 2007, 21:38
"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:
{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);
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!

"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.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#47

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 11. Okt 2007, 22:39
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 von cRayZo:
Zitat von Muetze1:
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.
Und nochmal: ReceiveText liefert dir komplett alles, was der Socket bis zu dem Aufruf von ReceiveText empfangen hat. Wenn du auf der einen Seite "inc:" und dahinter einen Text "blubb" schickst, dann ist die Chance mehr als gross, dass der Client beim OnClientRead z.B. schon "inc:blubb" empfangen hat. Und damit erhälst du bei dem ReceiveText-Aufruf schon "inc:blubb". Dies gibst du Copy und bekommst nur "inc" - das ":blubb" schmeisst du weg, da du das nirgendwo speicherst. Genauso gut kann es sein, dass er bisher nur "in" empfangen hat. Dein ReceiveText entfernt nunmal alles was er jemals zurück gegeben hat aus dem Socket. D.h. beim nächsten Aufruf bekommste dann z.B. vielleicht "c:bl" und beim nächsten Mal "ubb".

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.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#48

Re: Dateiaustausch zwischen clientsocket und serversocket..^

  Alt 12. Okt 2007, 22:13
Auch wenn es zuvor vielleicht recht harsch war: Wie siehts aus? Wie ist der Stand?
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 11:36 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