Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi TClientSocket / TSeverSocket --- Gruppenchat (https://www.delphipraxis.net/113220-tclientsocket-tseversocket-gruppenchat.html)

HugoHase 4. Mai 2008 20:17


TClientSocket / TSeverSocket --- Gruppenchat
 
Also ich Programmiere zur zeit einen Gruppenchat...
es functioniert auch alles ganz gut bis sich einer abmeldet ...
dazu könnt ihr ja mal ne Blick auf den Quellcode werfen:
(ich würde mich über hilfe freuen ... sehr sogar Thx im vorraus)

Server:
Delphi-Quellcode:
unit GUI;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp;

type
  TLog=record
   name : string[20];
   hash : string[4];
  end;

  TMember=record
   name : string[20];
   CO  : Integer;
  end;

  AMember = array of TMember;
  TLogFile = File of TLog;

  TFenster = class(TForm)
    MemoVerlauf: TMemo;
    ListBoxKontakte: TListBox;
    ButtonKick: TButton;
    ServerSocket: TServerSocket;
    procedure vON(text:string);
    procedure vAN(text:string);
    procedure vNE(text:string);
    procedure vLO(text:string);
    procedure vTE(text:string);
    procedure FormCreate(Sender: TObject);
    procedure ServerSocketClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocketClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocketClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ButtonKickClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Fenster: TFenster;
  Member:AMember;

implementation

{$R *.dfm}

procedure TFenster.FormCreate(Sender: TObject);
begin
 setlength(member,0);
end;

procedure TFenster.ServerSocketClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var i: integer;
begin
 sleep(500);
 SetLength(Member,length(Member)+1);
 Member[Length(member)-1].name:='Member'+IntToStr(length(Member)-1);
 Member[Length(member)-1].CO:=length(Member)-1;
 ListBoxKontakte.Clear;
 for i:=0 to length(Member)-1 do
 begin
  ListBoxKontakte.Items.Add(Member[i].name);
 end;
 ServerSocket.Socket.Connections[personen].SendText('CO'+IntToStr(length(Member)-1));
end;

procedure TFenster.ServerSocketClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin

end;

procedure TFenster.ServerSocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var merke,kopf,text:string;
begin
 merke:=Socket.ReceiveText;

 Kopf:=merke[1]+merke[2];
 Text:=copy(merke,3,length(merke)-2);

 if Kopf ='AN' then
  vAN(text);

 if Kopf = 'NE' then
  vNE(text);

 if Kopf = 'ON' then
  vON(text);

 if Kopf = 'LO' then
   vLO(text);

 if Kopf = 'TE' then
   vTE(text);
end;

procedure TFenster.vAN(text:string);
var ok      : boolean;
    i, CO   : integer;
    LogFile : TLogFile;
    mLog,Log : TLog;
begin
 Log.name:=copy(text,1,pos('|',text)-1);
 delete(text,1,pos('|',text));
 Log.hash:=copy(text,1,pos('|',text)-1);
 delete(text,1,pos('|',text));
 CO:=StrToInt(text);
 assignfile(LogFile,'LogFile.log');
 try
  reset(LogFile);
 except
 end;
 ok:=false;
 for i:=0 to FileSize(LogFile)-1 do
 begin
  Read(LogFile,mLog);
  if (Log.name=mLog.name)and(Log.hash=mLog.hash) then
   ok:=true;
 end;
 if ok then
 begin
  ServerSocket.Socket.Connections[CO].SendText('PWOK');
  MemoVerlauf.Lines.Add('*** Come in and find out '+Log.name+' ***');
  for i:=0 to length(Member)-1 do
  begin
   ServerSocket.Socket.Connections[i].SendText('TE'+'*** Come in and find out '+Log.name+' ***');
  end;
 end
 else
  ServerSocket.Socket.Connections[CO].SendText('PWKO');
 closeFile(LogFile);
end;

procedure TFenster.vNE(text:string);
var LogFile  : TLogFile;
    mLog, Log : TLog;
    i, CO    : integer;
    ok       : boolean;
begin
 Log.name:=copy(text,1,pos('|',text)-1);
 delete(text,1,pos('|',text));
 Log.hash:=copy(text,1,pos('|',text)-1);
 delete(text,1,pos('|',text));
 CO:=StrToInt(text);
 assignfile(LogFile,'LogFile.log');
 try
  reset(LogFile);
 except
  rewrite(LogFile);
 end;
 ok:=true;
 for i:=0 to FileSize(LogFile)-1 do
 begin
  Read(LogFile,mLog);
  if mLog.name=Log.name then
   ok:=false;
 end;
 if ok then
 begin
  Write(LogFile,Log);
  ServerSocket.Socket.Connections[CO].SendText('PWOK');
  MemoVerlauf.Lines.Add('*** Come in and find out '+Log.name+' ***');
  for i:=0 to length(Member)-1 do
  begin
   ServerSocket.Socket.Connections[i].SendText('TE'+'*** Come in and find out '+Log.name+' ***');
  end;
 end
 else
 begin
  ServerSocket.Socket.Connections[CO].SendText('PWKO');
 end;
 closeFile(LogFile);
end;

procedure TFenster.vLO(text:string);
var Liste, name : String;
    CO, i      : integer;
begin
 sleep(100);
 CO:=StrToInt(text);
 name:=Member[CO].name;
 for i:=CO to length(Member)-2 do
 begin
  Member[i].name:=Member[i+1].name;
  ServerSocket.Socket.Connections[Member[i].CO].SendText('CO'+IntToStr(Member[i].CO));
 end;
 SetLength(Member,length(Member)-1);
 ListBoxKontakte.Clear;
 Liste:='';
 for i:=0 to length(Member)-1 do
 begin
  Liste:=Liste+Member[i].name+'|';
  ListBoxKontakte.Items.Add(Member[i].name);
 end;
 for i:=0 to length(Member)-1 do
  ServerSocket.Socket.Connections[i].SendText('LI'+Liste);
 MemoVerlauf.Lines.Add('*** We will miss you '+name+' ***');
 for i:=0 to length(Member)-1 do
  ServerSocket.Socket.Connections[i].SendText('TE'+'*** We will miss you '+name+' ***');
end;

procedure TFenster.vON(text:string);
var name, Liste : String;
    CO, i      : integer;
begin
 name:=copy(text,1,pos('|',text)-1);
 delete(text,1,pos('|',text));
 CO:=StrToInt(text);
 ListBoxKontakte.Clear;
 Liste:='';
 for i:=0 to length(Member)-1 do
 begin
  if CO=Member[i].CO then
   Member[i].name:=name;
  ListBoxKontakte.Items.Add(Member[i].name);
  Liste:=Liste+Member[i].name+'|';
 end;
 for i:=0 to length(Member)-1 do
 begin
  ServerSocket.Socket.Connections[i].SendText('LI'+Liste);
 end;
end;

procedure TFenster.vTE(text:string);
var nachricht, name : string;
    mCO, i         : integer;
begin
 nachricht:=copy(text,1,pos('|',text)-1);
 delete(text,1,pos('|',text));
 mCO:=StrToInt(text);
 i:=-1;
 repeat
  inc(i);
 until Member[i].CO = mCO;
 name:=Member[i].name;
 MemoVerlauf.Lines.Add(name+' says: '+ nachricht);
 for i:=0 to length(Member)-1 do
 begin
  ServerSocket.Socket.Connections[i].SendText('TE'+name+' says: '+ nachricht);
 end;
end;

procedure TFenster.ButtonKickClick(Sender: TObject);
var i   :integer;
    name : string;
begin
 name:=ListBoxKontakte.Items.Strings[ListBoxKontakte.ItemIndex];
 for i:=0 to length(Member)-1 do
 begin
  if name = Member[i].name then
   ServerSocket.Socket.Connections[Member[i].CO].SendText('LO');
 end;
end;

end.

Client:
Delphi-Quellcode:
unit GUI;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ScktComp, uHash;

type
  TFenster = class(TForm)
    TextAus: TMemo;
    TextEin: TMemo;
    ListBoxOn: TListBox;
    PanelAn: TPanel;
    Status: TMemo;
    LabeledEditName: TLabeledEdit;
    LabeledEditPW: TLabeledEdit;
    ButtonOn: TButton;
    ClientSocket: TClientSocket;
    CheckBoxNew: TCheckBox;
    Timer: TTimer;
    PanelSever: TPanel;
    ComboBoxServer: TComboBox;
    ButtonStart: TButton;
    CheckBoxFH: TCheckBox;
    procedure ShowApplication;
    procedure vCO(text:string);
    procedure vPW(text:string);
    procedure vLI(text:string);
    procedure vTE(text:string);
    procedure ButtonOnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ClientSocketDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocketConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure TimerTimer(Sender: TObject);
    procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure LabeledEditNameKeyPress(Sender: TObject; var Key: Char);
    procedure LabeledEditPWKeyPress(Sender: TObject; var Key: Char);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure TextEinKeyPress(Sender: TObject; var Key: Char);
    procedure ButtonStartClick(Sender: TObject);
    procedure TextAusChange(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Fenster: TFenster;
  NName:String;
  CO:String;
  pw:string;
implementation

{$R *.dfm}

procedure TFenster.ButtonOnClick(Sender: TObject);
var hash:String;
begin
 if (LabeledEditName.Text<>'') and (pw<>'') then
 begin
  hash:=uHash.hash(PW,19,2141);
  pw:='';
  if CheckBoxNew.Checked then
   ClientSocket.Socket.SendText('NE'+LabeledEditName.Text+'|'+hash+'|'+CO)
  else
   ClientSocket.Socket.SendText('AN'+LabeledEditName.Text+'|'+hash+'|'+CO);
  LabeledEditPW.Text:='';
 end
 else
  showmessage('Type in name and password!');
end;

procedure TFenster.FormCreate(Sender: TObject);
begin
 randomize;
 pw:='';
end;

procedure TFenster.ClientSocketDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
 ClientSocket.Socket.SendText('LO'+CO);
 ClientSocket.Active:=false;
 close;
 SHowmessage('You are offline!'+#10+#13+'Server is gone!');
end;

procedure TFenster.ClientSocketConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
 Status.Lines.Add('Welcome, please type in your name and password!');
 ButtonOn.Enabled:=true;
end;

procedure TFenster.ClientSocketRead(Sender: TObject;
  Socket: TCustomWinSocket);
var merke,Kopf, Text:String;
begin
 merke:=Socket.ReceiveText;

 Kopf:=merke[1]+merke[2];
 Text:=copy(merke,3,length(merke)-2);

 if Kopf ='PW' then
  vPW(text);

 if Kopf = 'CO' then
  vCO(text);

 if Kopf = 'LI' then
  vLI(text);

 if Kopf = 'TE' then
  vTE(text);

 if Kopf = 'LO' then
  close;

end;

procedure TFenster.vPW(text:string);
begin
 if text='OK' then
 begin
  NName:=LabeledEditName.Text;
  ClientSocket.Socket.SendText('ON'+NName+'|'+CO);
  PanelAn.Hide;
  TextEin.SetFocus;
 end
 else
 begin
  Status.Lines.Add('Invalid password');
  Status.Lines.Add('Access denided');
  LabeledEditPW.Text:='';
  pw:='';
 end;
end;

procedure TFenster.vLI(text:string);
var na:string;
begin
 ListBoxOn.Clear;
 while length(text)>0 do
 begin
  na:=copy(text,1,pos('|',text)-1);
  delete(text,1,pos('|',text));
  ListBoxOn.Items.Add(na);
 end;
end;

procedure TFenster.vCO(text:string);
begin
 CO:=text;
end;

procedure TFenster.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
 if alphablendvalue<247 then
  AlphaBlendValue:=AlphaBlendValue+10
 else
  alphablendvalue:=255;
end;

procedure TFenster.TimerTimer(Sender: TObject);
begin
 if not Fenster.Active then
  if AlphaBlendValue>10 then
   AlphaBlendValue:=AlphaBlendValue-2
 else
  if alphablendvalue<247 then
   AlphaBlendValue:=AlphaBlendValue+10
  else
   alphablendvalue:=255;
end;

procedure TFenster.ClientSocketError(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
 case ErrorCode of
  10061 : begin
           ErrorCode:=0;
           showmessage('Sever not found!'+#10+#13+'Please, try again later!');
           close;
          end;
 end;
end;

procedure TFenster.LabeledEditNameKeyPress(Sender: TObject; var Key: Char);
begin
 case key of
 char(vk_return) : begin
                    key:=#0;
                    LabeledEditPW.SetFocus;
                   end;
 '|'            : key:=#0;
 else

 end;
end;

procedure TFenster.LabeledEditPWKeyPress(Sender: TObject; var Key: Char);
var i, anzahl : integer;
begin
 anzahl:=random(3);
 for i:=0 to anzahl do
  LabeledEditPW.Text:=LabeledEditPW.Text+'*';
 case key of
  chr(vk_return) : begin
                    ButtonOnClick(Sender);
                    key:=#0;
                   end;
  chr(vk_back)  : begin
                    LabeledEditPW.Text:='';
                    pw:='';
                    key:=#0;
                   end;

 else
  pw:=pw+key;
  key:=#0;
 end;
end;

procedure TFenster.FormClose(Sender: TObject; var Action: TCloseAction);
var FileName, m1,m2,m3 : string;
begin
 FileName:='D'+DateToStr(date)+' T';
 m1:=timetostr(time);
 m2:=copy(m1,1,pos(':',m1)-1);
 delete(m1,1,pos(':',m1));
 m2:=m2+'-';
 m3:=copy(m1,1,pos(':',m1)-1);
 delete(m1,1,pos(':',m1));
 m2:=m2+m3+'-'+m1;
 FileNAme:=FileName+m2;
 if DirectoryExists('Verlauf') then
 begin
  TextAus.Lines.SaveToFile('Verlauf\'+FileName+'.vlf');
 end
 else
 begin
  MkDir('Verlauf');
  TextAus.Lines.SaveToFile('Verlauf\'+FileName+'.vlf');
 end;
 ClientSocket.Active:=false;
end;

procedure TFenster.TextEinKeyPress(Sender: TObject; var Key: Char);
var text : string;
begin
 if key = chr(13) then
 begin
  key:=#0;
  text:=TextEin.Lines.Text;
  TextEin.Clear;
  if lowercase(text) = 'exit' then
   close;
  ClientSocket.Socket.SendText('TE'+text+'|'+CO);
 end;
end;

procedure TFenster.vTE(text:string);
begin
 TextAus.Lines.Add(text);
end;

procedure TFenster.ButtonStartClick(Sender: TObject);
begin
 ClientSocket.Host:=ComboBoxServer.Text;
 try
  ClientSocket.Active:=true;
 except

 end;
 PanelSever.Visible:=false;
end;

end.

toms 4. Mai 2008 20:18

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
Hallo HugoHase, was passiert denn, wenn sich jemand abmeldet?

Die Muhkuh 4. Mai 2008 20:19

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
Sicherlich schaut sich keiner 400 Zeilen Source durch, ohne jegliche Fehlerbeschreibung von Dir... :zwinker:

HugoHase 4. Mai 2008 21:37

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
also wenn ein client geschlossen wird sended er den text LO + seine Conectionnummer (CO)
dann geht die procedure vLO beim sever los
und dann kommt der Fehler:
"Windows Socket Error : Eine bestehende Verbindung wurde softwaregesteuert durch den Hostcomputer abgebrochen (10053), on API 'send'"
ich schätze der Server greift auf auf ne Verbindung zu die er nicht mehr hat ...
wenn ein client der auf einem anderen pc gestartet wurde beendet wird passiert das jedoch nicht
danke im vorraus

Net7 7. Mai 2008 17:22

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
Hi,

Delphi-Quellcode:
procedure TFenster.ServerSocketClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin

end;
Warum läßt du diese leer? Hier solltest du dem Server mitteilen welche Connection sich gerade verabschiedet hat, damit er diese verwerfen kann und nich weiter an eine Connection sendet, die nicht mehr vorhanden ist.

Mfg Net7

HugoHase 7. Mai 2008 19:28

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
Weil ich nicht weiß wie man raus bekommt welche Connection sich verabschieded hat ...
das wüsste ich gerne
wenn man nämlich annimmt bei einem betroffenen Client fällt das internet aus dann schickt ja der client ja nichts mehr der ist dann einfach nur weg
helft mir bitte :pale:

Net7 8. Mai 2008 07:09

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
Hmm..

also das läuft so, jede Connection hat eine Handlenummer die kannst du mit dem Befehl socket.Connections[socket.ActiveConnections-1].Handle ermitteln.
Somit kannst du jede aktive Verbindung über diese Nummer eindeutig identifizieren.

Beispiel:

Client Nr.1 hat socket.ActiveConnections-1; also 0 mit der Handlenummer zb. 1255
Client Nr.2 hat socket.ActiveConnections-1; also 1 mit der Handlenummer zb. 1599
...
usw.

Speicher also zu jeder Verbindung das Handle ab: Stichwort Array oder Record.

Wenn ein Client offline geht wird das Ereignis
ServerSocketClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); ausgelöst.

Sender:: TCustomWinSocket ist so freudlich und teilt dir die Handlenummer mit, die gerade offline gegangen ist. Über eine Schleife kannst du nun Ermitteln welches Handle zu welcher Verbindung paßt und diese, dann nicht mehr nutzen.

Bissel Code aus einem alten Projekt von mir.

Delphi-Quellcode:
//Clienten aus Liste löschen bei Event ClientonDisconnect    funktionsfähig
procedure TNet7Server.ClientDeleteList(DSocket: TCustomWinSocket);
(* -------------------------------------------------------------------------- *)
var
i: Integer;
i2: integer;
i3: integer;
HDL: Integer;
z: integer;

begin

      z := 0;



       for i := 0 to MaxAnzCon do
       begin
           if cv.HNr[i] = dsocket.Handle then
            begin


                   //wenn es die höchste Verbindungsnummer ist ,brauchen die anderen nicht angepasst werden
                   if (cv.Con[i] = socket.ActiveConnections-1) then
                    begin
                             debuglog('Gleich wird exit ausgelöst',-1,173);
                              cv.Con[i] := -1;
                              cv.HNr[i] := -1;
                              cv.isOnline[i] := false;
                              ClientListNow;
                              exit;     // Und raus

                    end;



                  // z:=i;
                   i3 := cv.Con[i]; //merke deine Connummer damit nur die verkleinert werden die grösser sind als du
                   cv.Con[i] := -1;
                   cv.HNr[i] := -1;
                   cv.isOnline[i] := false;


                         { Connections den Handles anpassen, ab der cons
                        die aufgelöst wurde müssen die anderen cons die dahinter u Gr. sind um -1 aufrücken
                         [0][1][2][3][x]<-- war mal con 4 [4][5][6]
                         }
                   for i2 := 0  to MaxAnzCon do
                      begin

                                                    //nur die verkleinern die gr als gelöschte con
                             if (cv.Con[i2] >= 0) and (cv.Con[i2] > i3) then
                              begin

                                    cv.Con[i2] := cv.Con[i2] -1;

                               end;

                      end;

               end;

       end;


      ClientListNow;


end;
Ich hoffe das es im Groben und Ganzen alles erläutert. cv ist ein Record wo ich alle Daten der Verbindung abspeichere.


Mfg Net7

Muetze1 8. Mai 2008 10:07

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
Zitat:

Zitat von Net7
also das läuft so, jede Connection hat eine Handlenummer die kannst du mit dem Befehl socket.Connections[socket.ActiveConnections-1].Handle ermitteln.
Somit kannst du jede aktive Verbindung über diese Nummer eindeutig identifizieren.

Wozu eine Eigenschaft zum Vergleich nehmen, wenn die Instanz über die Verbindung (genauso wie das Handle) eindeutig ist?

Sprich: Socket.Connections[] Elemente entsprechen genau den bei den Handlern übergebene Socket Instanzen. Somit also noch deutlich einfacher...

Zitat:

Zitat von Net7
Sender:: TCustomWinSocket ist so freudlich und teilt dir die Handlenummer mit, die gerade offline gegangen ist. Über eine Schleife kannst du nun Ermitteln welches Handle zu welcher Verbindung paßt und diese, dann nicht mehr nutzen.

Diese Elemente werden danach von selbst aus der Socket.Connections[] Eigenschaft ausgetragen.

Und auch zusätzliche Informationen zu einer Verbindung (z.B. Benutzernamen) muss man nicht extra verwalten und dann aufwendig die Kreuzverbindung zwischen Connections[] und der eigenen Liste pflegen, sondern man kann jedem Socket in der Data Eigenschaft Daten hinterlegen. Das kann eine Instanz sein oder ein Zeiger auf einen Record. Im OnConnect anlegen, im OnDisconnect wieder freigeben und bei allem dazwischen hat man die Informationen direkt zur Verfügung, sogar gleich mit übergeben bei jedem Eventhandler, da es, wie zuvor geschrieben, die gleiche Instanz ist.

HugoHase 8. Mai 2008 14:46

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
danke net7
ich mach mich heute abend nocmal ran
es wird mir dann geholfenhaben ^^ ich sag dann noch mal was dazu
thx

Net7 8. Mai 2008 15:29

Re: TClientSocket / TSeverSocket --- Gruppenchat
 
Zitat:

Und auch zusätzliche Informationen zu einer Verbindung (z.B. Benutzernamen) muss man nicht extra verwalten und dann aufwendig die Kreuzverbindung zwischen Connections[] und der eigenen Liste pflegen, sondern man kann jedem Socket in der Data Eigenschaft Daten hinterlegen. Das kann eine Instanz sein oder ein Zeiger auf einen Record. Im OnConnect anlegen, im OnDisconnect wieder freigeben und bei allem dazwischen hat man die Informationen direkt zur Verfügung, sogar gleich mit übergeben bei jedem Eventhandler, da es, wie zuvor geschrieben, die gleiche Instanz ist.
@Muetze1

Ich gebe zu, das ich das bei meinem Kenntnisstand heute, die Verwaltung auch anders machen würde, jedoch gibt es auch Leute die sich gerade erst damit auseinandersetzen, da möchte ich nicht gleich übertreiben. Denn so verstehen sie das Thema nicht, finden die ganze Sache viel zu kompliziert (was sie ja eigendlich nicht ist) und geben auf. Ich kann mich auch daran erinnern wie ich angefangen habe, dann schaut man sich Tutorials an die einem eigendlich nichts sagen weil sie einfach zu weit gehen.

Ich zitiere da mal ein Post aus meinem Forum:

Zitat:

... Klasse ich muss Dir an dieser Stelle mal ein Kompliement machen, Net7. Deine Demos sind immer so einleuchtend, dass sie kaum einer näheren Erläuterung bedürfen. Grad hab ich nach nem Netzwerktutorial gesucht. Da findet man hunderte. Aber zu kapieren was Deine Demo macht, dauert nur fünf Minuten und schon weiß ich wieder, was ich wissen wollte.....


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:35 Uhr.
Seite 1 von 2  1 2      

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