![]() |
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. |
Re: Sehr langen String mit Clientsocket an Serversocket send
*grins* Warum´s einfach machen, wenn´s auch kompliziert geht?! *g*
|
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. |
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. |
Re: Sehr langen String mit Clientsocket an Serversocket send
Delphi-Quellcode:
habs net getestet müsste aber so gehen.
//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; |
Re: Sehr langen String mit Clientsocket an Serversocket send
Zitat:
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 |
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 . |
Re: Sehr langen String mit Clientsocket an Serversocket send
Zitat:
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; |
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? |
Re: Sehr langen String mit Clientsocket an Serversocket send
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:24 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz