![]() |
Re: Indy TCPServer -> Client
Also Indy TCP ist auch nicht gerade meines :).
1. beim connecten speicherst du dir then thread in eine liste und damit kannst du wieder auf die verbindung zugreifen ( die methode ist eigentlich schlecht, weil der thread beim disconnecten zerstört wird und es leicht zu fehlern kommen kann - auch bei socket errors könnte es hier zu problemen kommen). 2. normalerweise haben diese threads .data eigenschaften wo eben userdaten gespeichert werden. Das ist thread sicher - heißt wenn der thread (connection) beendet wird, sind auch die daten weg - und es kommt nicht so leicht zu ner access violation .... Damit kannst aber leicht erkennen welcher user hinter dem Thread (connection) steht. Indy ist da soweit ich mich erinnere nicht ganz so komfortabel wie tserversocket also mußt du dir die funktionen glaub ich selbst basteln ( ich hab auf die schnelle keine funktion gefunden die dir alle threads auflisten würde ). Das bedeutet du mußt bei indy vermutlich wirklich eine liste aller aktiven threads führen - doof eigentlich. Und jedesmal wenn ein connect kommt einen neuen eintrag auf der liste machen - wenn ein disconnect kommt den eintrag löschen (und am bessten die liste zusammenschieben). Und auf jeden fall alles in try except blöcke weil sonst stürtzt dir das ding nur noch ab :). In der onError solltest du ebenfalls schauen, daß du fehlerhafte sockets zu bekommst und auch die liste aktuell hältst. Arnulf |
Re: Indy TCPServer -> Client
Zitat:
Nun zum problem mot dem lesen beim Client. Die beste und auch einfachste Lösung ist es, einen Timer zu benutzen. 300ms haben sich als praktikabler Wert erwiesen. Den initialisiertst du, bevor du den Client-Connect durchführst. Das sieht als Code etwa so aus:
Delphi-Quellcode:
{/////////////////////////////////////////}
{*** data available and read/send data ***} {/////////////////////////////////////////} function NetworkDataAvailable(ACon: TIdTCPConnection): boolean; begin RWSynchro.BeginRead; {*** darf auch TCriticalSection sein ***} if ACon.Connected then begin Result := ACon.InputBuffer.Size > 0; if not Result then begin try ACon.ReadFromStack(False, 1, False); Result := ACon.InputBuffer.Size > 0; except Result:= false; end; end; // of if not Result then begin end // of if ACon.Connected then begin else Result := False; RWSynchro.EndRead; end; // of function NetworkDataAvailable(ACon: TIdTCPConnection): boolean procedure TChatClt.LookForData(Sender: TObject); begin if FTCPClient.Connected then begin FDataAvailable:= NetworkDataAvailable(FTCPClient); if FDataAvailable then DoReceiveData; end; // of if FTCPClient.Connected then begin end; // of procedure TChatClt.LookForData(Sender: TObject) procedure TChatClt.DoReceiveData(Sender: TObject); var FStream: TMemoryStream; begin FStream:= TMemoryStream.Create; {*** hier daten einlesen, am prakikabelsten ist ein stream ***} {*** dann können auch verschlüsselungen benutzt werden ***} {*** Bsp.: ***} FTCPClient.ReadStream(FStream, -1, false); {*** ab hier verarbeiten ***} end; |
Re: Indy TCPServer -> Client
Zitat:
|
Re: Indy TCPServer -> Client
Schau dir auch mal die Indy-Demos an, da sihst du ja, wies funktioniert ;)
|
Re: Indy TCPServer -> Client
Ui... das haut mich um^^ Ich weiß nicht wirklich was damit anzufangen weil ich kaum was davon verstehe :([/quote]
Na dann. Zunächst baust du dir mal ein Objekt mit dem schönen Namen TChatClient oder eben wie im Bsp. TChatClt. Etwa so:
Delphi-Quellcode:
Nun bindest du die Unit in den jeweiligen Modulen ein, in den denen Daten empfangen werden könnten oder Aufrufe von ChatClient nötig sind.uses SysUtils, Classes, DateUtils, IdTCPClient; type TChatClient = class(TObject) private FTCPClient : TIdTCPClient; FReadDataTimer: TTimer; procedure LookForData(Sender: TObject); {*** das ding ist für den timer ***} procedure DoReadData(Sender: TObject); {*** das ding liest deine daten vom TCPClient ***} procedure SendDataToServer(strm: TSteam); public constructor Create; {*** weil von TObject abgeleitet ohne Owner und override ***} destructor Destroy; {*** desgleichen ***} function InitTcpClient(Ahost: string; Aport: integer): boolean; {*** den Client initilisieren ***} // hier die methoden zum versenden von daten deklarieren // die bauen den Stream zusammen und senden der SendDataToServer zum Chat-Server // der kümmert sich dann um die weiterleitung zu dem oder den Empfängern procedure SendClientLogin; procedure SendChatMessage(Receiver, Msg: string); {*** Bsp: Receiver := 'Paul;Paula;Paulaner;Paulinchen'; ***} {*** liest man natürlich per programm-funktion ein ***} {*** Im Stream könnte man die User zum Bespiel mit dem Feld: '@User' gefolgt von '#len' für die Datenlänge, das sind Feldnamen. Nach '#len' trägt man per Stream.WriteBuffer(length(Receiver), SizeOf(integer)); die stringlänge der Receiverliste ein. Das liest man dann mit nem Scanner vom Stream wieder ein: Bsp.: while (Stream.Position < Stream.Size) do begin Stream.ReadBuffer(c, SizeOf(Char)); case c of '@': inc(Stream.Position, 4); // Position auf '#' setzen '#': begin inc(Stream.Position, 3); Stream.ReadBuffer(StrLen, SizeOf(integer)); SetLength(UserList, StrLen); Stream.ReadBuffer(UserList[1], StrLen); // end; // get Listlength end; end; ***} end; // of TChatClient var ChatClient: TChatClient; iplementation constructor TChatClient.Create; begin inherited Create; FTCPClient := TIdTCPClient.Create(nil); FReadDataTimer:= TTimer.Create(nil); FReadDataTimer.Interval:= 300; FReadDataTimer.OnTimer := LookForData; FReadDataTimer.Enable := false; end; // of constructor TChatClient.Create // jetzt den Client initialisieren function TChatClient.InitTcpClient(Ahost: string; Aport: integer): boolean; begin FTCPClient.Host:= Ahost; FTCPClient.Port:= Aport; FTCPClient.Connect; Result:= FTCPClient.Connected; if Result then begin // wenn noch mehr zu initialisieren dann hier FReadDataTimer.Enable:= true; {*** ab jetzt läuft der Timer und ruft ***} {*** in regelmäßigen Abständen LookForData auf ***} {*** wenn Daten da sind ruft LookForData DoReadData auf und du hast deine Daten zur Verfügung ***} end; end; // of function TChatClient.InitTcpClient(host: string; port: integer): boolean Das war jetzt Stoff für das 2 Semester Informatik. Viel Spaß damit, hoffentlich hilft es... |
Re: Indy TCPServer -> Client
Zitat:
Naja dann wende ich dann mal die böse Methode copy&paste&nixverstehen an :mrgreen: wobei ich befürchte das ich zumindest ansatzweise verstehen muss, weil ichs sonst nicht anzuwenden weiß ... |
Re: Indy TCPServer -> Client
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:23 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