AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Indy TCPServer -> Client
Thema durchsuchen
Ansicht
Themen-Optionen

Indy TCPServer -> Client

Ein Thema von Neutral General · begonnen am 4. Jun 2005 · letzter Beitrag vom 23. Jun 2005
Antwort Antwort
Seite 2 von 2     12   
Arnulf

Registriert seit: 28. Okt 2004
Ort: Wien
271 Beiträge
 
#11

Re: Indy TCPServer -> Client

  Alt 9. Jun 2005, 10:12
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
  Mit Zitat antworten Zitat
hardy1234

Registriert seit: 8. Aug 2004
Ort: Hamburg
26 Beiträge
 
Delphi 7 Enterprise
 
#12

Re: Indy TCPServer -> Client

  Alt 20. Jun 2005, 01:07
Zitat von Neutral General:
Ja ich denke das würde gehen aber geht es nicht anders ?
Im Notfall würde ich das machen ...
Das mit dem Server beim Client lass mal, das wird nix. Gesetzt den Fall du wolltest das Ding im Inet betreiben und sitzt hinter nem router(gilt natürlich auch für andere User), würdest du durch den router durch keine Connection zu deinem Server(dem beim Client hinkriegen. Der router sperrt i.d.R. jeden Zugang von außen.

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;
Es gibt keinen schöneren Tag als den heutigen. Der gestrige ist vorbei und von den kommenden weiß man nicht was sie bringen.
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#13

Re: Indy TCPServer -> Client

  Alt 20. Jun 2005, 16:45
Zitat von hardy1234:
Zitat von Neutral General:
Ja ich denke das würde gehen aber geht es nicht anders ?
Im Notfall würde ich das machen ...
Das mit dem Server beim Client lass mal, das wird nix. Gesetzt den Fall du wolltest das Ding im Inet betreiben und sitzt hinter nem router(gilt natürlich auch für andere User), würdest du durch den router durch keine Connection zu deinem Server(dem beim Client hinkriegen. Der router sperrt i.d.R. jeden Zugang von außen.

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;
Ui... das haut mich um^^ Ich weiß nicht wirklich was damit anzufangen weil ich kaum was davon verstehe
Michael
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#14

Re: Indy TCPServer -> Client

  Alt 20. Jun 2005, 17:17
Schau dir auch mal die Indy-Demos an, da sihst du ja, wies funktioniert
  Mit Zitat antworten Zitat
hardy1234

Registriert seit: 8. Aug 2004
Ort: Hamburg
26 Beiträge
 
Delphi 7 Enterprise
 
#15

Re: Indy TCPServer -> Client

  Alt 21. Jun 2005, 02:22
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:

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
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.

Das war jetzt Stoff für das 2 Semester Informatik. Viel Spaß damit, hoffentlich hilft es...
Es gibt keinen schöneren Tag als den heutigen. Der gestrige ist vorbei und von den kommenden weiß man nicht was sie bringen.
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#16

Re: Indy TCPServer -> Client

  Alt 21. Jun 2005, 20:22
Zitat:
Das war jetzt Stoff für das 2 Semester Informatik. Viel Spaß damit, hoffentlich hilft es...
omg kein Wunder das ich das nicht verstehe
Naja dann wende ich dann mal die böse Methode copy&paste&nixverstehen an
wobei ich befürchte das ich zumindest ansatzweise verstehen muss, weil ichs sonst nicht anzuwenden weiß ...
Michael
  Mit Zitat antworten Zitat
hardy1234

Registriert seit: 8. Aug 2004
Ort: Hamburg
26 Beiträge
 
Delphi 7 Enterprise
 
#17

Re: Indy TCPServer -> Client

  Alt 23. Jun 2005, 08:15
Zitat von Neutral General:
Zitat:
Das war jetzt Stoff für das 2 Semester Informatik. Viel Spaß damit, hoffentlich hilft es...
omg kein Wunder das ich das nicht verstehe
Naja dann wende ich dann mal die böse Methode copy&paste&nixverstehen an
wobei ich befürchte das ich zumindest ansatzweise verstehen muss, weil ichs sonst nicht anzuwenden weiß ...
Es soll da bei Delphi so ne hübsche Einrichtung namens Debugger geben. Da baut man sich dann halt nen kleinen Client und sendet Daten und den Server untersucht man mit dem Debugger. Dat geiht. Dann siehste Du schon wie das abläuft. Ich würde Dir aber raten lieber die UDP-Compos von Indy zu nehmen. Dann brauchst Du beim Server den Feetz mit dem Execute und Connect/Disconnect nicht machen. Um die Verbindung zu testen kan man ja zur not eine normale TCP-Komponente auf nem anderen Port verwenden. Dann weiß man ob der Server da ist.
Es gibt keinen schöneren Tag als den heutigen. Der gestrige ist vorbei und von den kommenden weiß man nicht was sie bringen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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 14:08 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