Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Sehr langen String mit Clientsocket an Serversocket senden.. (https://www.delphipraxis.net/17044-sehr-langen-string-mit-clientsocket-serversocket-senden.html)

Jens Schumann 27. Feb 2004 12:52

Re: Sehr langen String mit Clientsocket an Serversocket send
 
Hallo,
ich hatte kein Lust lange rum zu suchen.
Deshalb habe mir eine kleine unit geschrieben und in ein Package gepackt.
Diese Package habe ich installiert. Jetzt sind die Komponenten da.
Delphi-Quellcode:
unit MySocktes;

interface

uses classes, ScktComp;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Sockets',[TClientSocket,TServerSocket]);
end;

end.

Evian 27. Feb 2004 12:56

Re: Sehr langen String mit Clientsocket an Serversocket send
 
*grins* Warum´s einfach machen, wenn´s auch kompliziert geht?! *g*

Jens Schumann 27. Feb 2004 14:09

Re: Sehr langen String mit Clientsocket an Serversocket send
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe ich meinen Sourcen und meiner Erinnerung gekramt und ein
Quick&Dirty Beispiel zusammengestellt. clSendTStrings.exe (Client) sendet über eine
blockierende Verbindung und TWinSocketStream den Inhalt einer TListBox an
svSendTStrings.exe (Server). Der Server lädt damit seine TLisbox.

AnTiPrimaTe 28. Feb 2004 11:50

Re: Sehr langen String mit Clientsocket an Serversocket send
 
Also wenn man große String-Daten verschickt und ganz ganau wissen will
wann und ob die komplett angekommen sind, sollte man am besten
eine Anfang- und End- Signaturen verwenden.
Irgendein Zeichen, das nicht in den vorkommen kann (z.B. HEX 13 und HEX 14 oder so).
Dann speichert man jeden angekommenen Frame in ein Buffer
und überprüft, ob Anfang und Ende im Buffer vorkommen,
wenn das der Fall ist - Daten sind da, wenn nicht auf weitere Pakete warten.

Manzoni 28. Feb 2004 12:42

Re: Sehr langen String mit Clientsocket an Serversocket send
 
Delphi-Quellcode:
//Client
procedure TForm1.senden;
var TextStream : TStringStream;
begin
  textstream:=TStringStream.Create(ListBox1.CommaText);
  textstream.Position:=0;
  ClientSocket1.Socket.SendStream(textstream);
end;

//Server
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var iLen: Integer;
    Bfr: Pointer;
    text: TStringStream;
begin
  iLen := Socket.ReceiveLength;
  GetMem(Bfr, iLen);
  Socket.ReceiveBuf(Bfr^, iLen);
  text:=TStringStream.Create('');
  text.Write(Bfr^, iLen);
  text.Position:=0;
  ListBox1.Lines.Add(text.DataString);
end;
habs net getestet müsste aber so gehen.

Jens Schumann 28. Feb 2004 13:17

Re: Sehr langen String mit Clientsocket an Serversocket send
 
Zitat:

Zitat von Manzoni
habs net getestet müsste aber so gehen.

Nein - geht so nicht !!!

Wenn die vom Client gesendete Datenmenge nicht in ein Paket passt, wird die Datenmenge
aufgeteilt und mit mehreren Pakten versandt. Das führt dazu, dass das ClientRead Event
mehr als einmal feuert. Was dann in der Listbox steht kann sich ja dann denken.

Jetzt sage ich es zum letzen Mal: Blockierende Verbindungen und TWinsocketStream

AnTiPrimaTe 28. Feb 2004 17:01

Re: Sehr langen String mit Clientsocket an Serversocket send
 
bei blocked sockets kann es aber genauso zu Fragmentierung kommen,
wenn die Daten groß sind, dann werden die je von TCP-Stack
gesplittet, Netz dazwischen spielt auch ne Rolle.
man muss auf jeden Fall selbst eigene Frames "verpacken",
wie ich bereits oben geschrieben hab, mit Start- und End-Signaturen
.

Jens Schumann 29. Feb 2004 07:31

Re: Sehr langen String mit Clientsocket an Serversocket send
 
Zitat:

Zitat von AnTiPrimaTe
bei blocked sockets kann es aber genauso zu Fragmentierung kommen,
wenn die Daten groß sind, dann werden die je von TCP-Stack
gesplittet, Netz dazwischen spielt auch ne Rolle.
man muss auf jeden Fall selbst eigene Frames "verpacken",
wie ich bereits oben geschrieben hab, mit Start- und End-Signaturen
.

Definitiv Nein -> keine Start- und End-Signaturen.

Wenn der Client connected (Dann sendet der Client auch sofort) wird im OnGetThread von TServerSocket ein neuer TServerClientThread erzeugt. Dadurch wird dann im neuen TServerClientThread (oder aus dem Threadpool) die Methode ClientExecute aufgerufen. Das folgende Beispiel basiert übrigends auf
dem Beispiel aus der OH.
Delphi-Quellcode:
procedure TClientThread.ClientExecute;
var
  szBuffer    : array[0..1024] of Char;
  aWSStream   : TWinSocketStream;
  iBytes      : Integer;
  aMStream    : TMemoryStream;
  DataPosition : Integer;
begin
  FillChar(szBuffer, SizeOf(szBuffer), #0);
  while not Terminated and ClientSocket.Connected do
  begin
    try
      // Blockierende Sockets mit 60 Sekunden Timeout
      aWSStream := TWinSocketStream.Create(ClientSocket, 60000);
      aMStream := TMemoryStream.Create;
      try
        // Client muss innerhalb von 5 Sekunden mit der Übertragung beginnen
        if aWSStream.WaitForData(5000) then
          repeat
            iBytes := aWSStream.Read(szBuffer, SizeOf(szBuffer));
            if iBytes = 0 then // Wenn keine Daten mehr aus der Verbindung gelesen werden können,
                               // kappe die Verbindung zum Cient. Dadurch liefert auch WaitForData
                               // False und die Repeat-Schleife wird verlassen.
              ClientSocket.Close
            else  
              aMStream.WriteBuffer(szBuffer, iBytes);
          until not aWSStream.WaitForData(2000); // Solange aus Verbindung lesen, wie
                                                 // wie Verbindung bereit ist.
        // Ab hier sind alle Daten, die gesendet wurden in aMStream !!!!!
        FStream.Clear;
        aMStream.Seek(0,soFromBeginning);
        // Der Client hat vor den eigentlichen Nutzdaten einen einen Record in den TWinSocketStream
        // geschrieben. Dieser Record enthält eine sog. CommandID. Dieser Record muss jetzt erstmal
        // aus aMStream gelesen werden.
        DataPosition:=aMStream.Read(FCommand,SizeOf(TClSvCommand));
       
        // Kopiere jetzt ab Dataposition die Nutzdaten nach FStream
        FStream.CopyFrom(aMStream,aMstream.Size-DataPosition);

       // Entscheide über die CommandID was zu tun ist.
        Case FCommand.CommandID of
          iCommandLoadMemo : Synchronize(UpdateMemo);
          iCommandCLearMemo : Synchronize(ClearMemo);
          end;
      finally
        aWSStream.Free;
        ClientSocket.Close;
        aMStream.Free;
      end;
    except
      HandleException;
      end;
  end;

end;

AnTiPrimaTe 29. Feb 2004 11:30

Re: Sehr langen String mit Clientsocket an Serversocket send
 
das alles heißt ja nicht, dass die Daten nicht fragmentiert werden,
im Beispiel wird das nur dadurch gelöst, dass Du immer die Daten liest,
solange es geht. Das geht auch, im Thread, und nur wenn du ein
Frame in einer Stunde abschickst.
Start und End-Signaturen sind immer wichtig,
stell dir vor, Du willst zwei Memo-Felder oder was auch immer füllen,
schickt Deine 2 Frames innerhalb 1 Sekunde ab
und es kommen 3 Datenpackete (weil die unterwegs defragmentiert wurden),
wie willst Du die bearbeiten, wenn Du nicht weiß wo der Anfang und das Ende sind?

Jens Schumann 29. Feb 2004 11:53

Re: Sehr langen String mit Clientsocket an Serversocket send
 
Zitat:

Zitat von AnTiPrimaTe
wie willst Du die bearbeiten, wenn Du nicht weiß wo der Anfang und das Ende sind?

Das TCP sorgt für die richtige Reihenfolge.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:47 Uhr.
Seite 2 von 4     12 34      

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