Autor Beitrag
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 29.05.06 22:50 
Narses´ Netzwerk-Tutorials - Navigation
  1. FAQ-Beitrag: Socket-Komponenten nachinstallieren (ab D7)
  2. hier :arrow: Netzwerk-Basics - Minimaler Chat für Anfänger
  3. Terminatorzeichen-Protokoll - Grundlagen
  4. Terminatorzeichen-Protokoll - Erweiterungen
  5. Binär-Protokoll - Für Fortgeschrittene
  6. Netzwerk-Spiel - Multiplayer TicTacToe
  7. UDP LAN-Chat - Der Chat ohne Server
Wie macht man einen LAN/Internet-Chat mit TServerSocket und TClientSocket?

Hier ist ein Anfänger-Tutorial für einen (wirklich minimalen) Netzwerk-Chat auf Basis der Socket-Komponenten (TServerSocket und TClientSocket). Falls die Sockets nicht in der Komponenten-Palette verfügbar sein sollten, ist im oben erwähnten FAQ-Beitrag eine ausführliche Anleitung zur Nachinstallation. Das Tutorial ist mit Delphi 7 Pro erstellt worden (ich sehe aber keine Probleme mit anderen Delphi-Versionen, solange die Socket-Komponenten installiert sind). In den Personal Editions von Delphi sind die Socket-Komponenten leider nicht in der IDE verfügbar, können aber trotzdem dynamisch verwendet werden. Mehr dazu ganz am Ende des Textes bei den Anhängen.

Wir werden für unseren Chat zwei Programme schreiben, einen Client, den die Chat-Teilnehmer verwenden werden und einen Server, der die Clients miteinander verbindet. Nochmal deutlich: nur einmal das Server-Programm starten und dann benutzt jeder einen Client, um am Chat teilzunehmen (auch der, der das Server-Programm gestartet hat!). ;) Die Clients verbinden sich dann mit dem einen Server-Programm (wie das genau geht, kommt gleich noch, bitte weiterlesen).

Zunächst das Server-Programm. Wir starten die IDE und legen ein neues Projekt an. Damit wir nicht ganz so viel an der Oberfläche herumbasteln müssen, hier das Formular in der Textdarstellung. Zum Übernehmen einfach das leere Formular anklicken, ALT+F12 drücken, dann wird in die Textdarstellung gewechselt. Jetzt den Text unten markieren, kopieren und dann den Inhalt im IDE-Fenster für das Formular komplett ersetzen (alles markieren und den kopierten Text von hier einfügen):
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
object Form1: TForm1
  Left = 226
  Top = 121
  Width = 209
  Height = 132
  Caption = 'Server'
  Color = clBtnFace
  Constraints.MinHeight = 132
  Constraints.MinWidth = 209
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  Position = poDesktopCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Log: TMemo
    Left = 8
    Top = 8
    Width = 185
    Height = 89
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 0
  end
  object ServerSocket1: TServerSocket
    Active = False
    Port = 0
    ServerType = stNonBlocking
    OnClientRead = ServerSocket1ClientRead
    Left = 88
    Top = 40
  end
end

Mit ALT+F12 schalten wir wieder in die grafische Darstellung des Formulars zurück. Jetzt können wir den Code übernehmen, dabei ersetzen wir den Standard-Quelltext in der IDE einfach komplett:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
unit Unit1;

interface

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

const
  MY_PORT = 12345// an diesem Port melden sich die Clients

type
  TForm1 = class(TForm)
    Log: TMemo;
    ServerSocket1: TServerSocket;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// beim Programmstart ausführen
procedure TForm1.FormCreate(Sender: TObject);
begin
  ServerSocket1.Port := MY_PORT; // den Port eintragen
  ServerSocket1.Open; // Server aktivieren
  Log.Lines.Add('Server online.');
end;

// beim Programmende ausführen
procedure TForm1.FormDestroy(Sender: TObject);
begin
  ServerSocket1.Close; // Server deaktivieren
end;

// Daten von einem Client eingetroffen
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
  var
    MyMessage: AnsiString;
    i: Integer;
begin
  // Nachricht lesen und davor die IP des Absenders setzen
  MyMessage := Socket.RemoteAddress+': '+Socket.ReceiveText;
  Log.Lines.Add(MyMessage); // Nachricht lokal ausgeben
  // und an alle verbundenen Clients senden
  for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
    ServerSocket1.Socket.Connections[i].SendText(MyMessage);
end;

end.

Hier ein paar kurze Erläuterungen zum Quelltext:
Ganz am Anfang definieren wir eine Konstante für den Port, auf dem die Kommunikation stattfinden soll:
ausblenden Delphi-Quelltext
1:
2:
const
  MY_PORT = 12345// an diesem Port melden sich die Clients

Einen Port kann man sich als virtuelle Steckdose an einem PC vorstellen. Damit ist es möglich, gleichzeitig mehrere Verbindungen über die gleiche IP-Adresse abzuwickeln. Dabei gilt es allerdings zu beachten, dass es bestimmte vordefinierte Ports gibt (sog. "well known ports"), die man nicht für eigene Anwendungen verwenden sollte. Dieser reservierte Bereich geht von 1-1024 (TCP). Fazit: Für eigene Anwendungen sollte man Portnummern oberhalb 1024, noch besser fünfstellige, verwenden.

Im FormCreate-Ereignis weisen wir den Port zu und aktivieren dann den Serverdienst. Ab jetzt können sich Clients mit dem Server verbinden. Dazu braucht der Client die IP-Adresse des PCs, auf dem der Server läuft und die Portnummer, an der der Server auf Clients wartet. Dazu später beim Client mehr.

Im FormDestroy-Ereignis schließen wir noch den Serverdienst, das Programm soll ja beendet werden. Dabei werden eventuell noch verbundene Clients zwangsgetrennt.

Bleibt nur noch das OnClientRead-Ereignis des Servers, dass wir uns jetzt ganz genau ansehen werden:
ausblenden Delphi-Quelltext
1:
2:
// Daten von einem Client eingetroffen
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);

Dieses Ereignis tritt ein, wenn eine Verbindung zu einem Client Daten empfangen, oder anders gesagt, wenn ein Client Daten gesendet hat. Dabei wird in Sender die Komponente geliefert, die das Ereignis ausgelöst hat (hier: ServerSocket1) und in Socket die Verbindung, die Daten empfangen hat (hier: ein Element des ServerSocket1.Socket.Connections[]-Array).
ausblenden Delphi-Quelltext
1:
2:
  // Nachricht lesen und davor die IP des Absenders setzen
  MyMessage := Socket.RemoteAddress+': '+Socket.ReceiveText;

Wir bauen uns hier aus Socket.RemoteAddress, das die IP-Adresse des Clients enthält, und aus Socket.ReceiveText, was die gesendeten Daten liefert, ein eigenes Nachrichtenformat zusammen. Auf diese Weise können wir die Nachrichten wenigstens grob unterscheiden. Warum nehmen wir keine Nicknames? Das geht zwar theoretisch, allerdings wird es an dieser Stelle schon schwer, ohne ein Protokoll auszukommen. Wir wollen den Rahmen dieses Tutorial nicht sprengen und verzichten deshalb auf Nicknames. Wer an dieser Stelle mehr wissen möchte, sollte mal hier nachsehen. ;)
ausblenden Delphi-Quelltext
1:
  Log.Lines.Add(MyMessage); // Nachricht lokal ausgeben					

Damit schreiben wir die Nachricht in das Protokoll-Fenster des Servers.

ausblenden Delphi-Quelltext
1:
2:
3:
  // und an alle verbundenen Clients senden
  for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
    ServerSocket1.Socket.Connections[i].SendText(MyMessage);

Das sind eigentlich die entscheidenden Zeilen des Server-Codes: Die Schleife läuft über die Anzahl der aktuell verbundenen Clients (startet mit 0, deshalb -1 am Ende) und sendet an jede Verbindung den empfangenen Text (IP+Nachricht). Auf diese Weise erhalten alle Clients den gesendeten Text, der nur von einem Client kam.

Jetzt zum Client. Wir starten eine weitere IDE und legen ein neues Projekt an (wir wollen ja auch zwei Programme schreiben). Hier die Formulardaten in Textform, wie beim Server einfach mit ALT+F12 ersetzen:
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
object Form1: TForm1
  Left = 212
  Top = 118
  Width = 227
  Height = 235
  Caption = 'Client'
  Color = clBtnFace
  Constraints.MinHeight = 235
  Constraints.MinWidth = 227
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  Position = poDesktopCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 8
    Top = 8
    Width = 71
    Height = 13
    Caption = 'Serveradresse:'
  end
  object Label2: TLabel
    Left = 8
    Top = 48
    Width = 41
    Height = 13
    Caption = 'Protokoll'
  end
  object Label3: TLabel
    Left = 8
    Top = 160
    Width = 111
    Height = 13
    Anchors = [akLeft, akBottom]
    Caption = 'Nachricht zum Senden:'
  end
  object ServerAdress: TEdit
    Left = 8
    Top = 24
    Width = 121
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 0
    Text = 'localhost'
  end
  object BtnSend: TButton
    Left = 136
    Top = 174
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Caption = '&Senden'
    TabOrder = 1
    OnClick = BtnSendClick
  end
  object Log: TMemo
    Left = 8
    Top = 64
    Width = 201
    Height = 89
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 2
  end
  object Online: TCheckBox
    Left = 136
    Top = 26
    Width = 73
    Height = 17
    Anchors = [akTop, akRight]
    Caption = '&Online'
    TabOrder = 3
    OnClick = OnlineClick
  end
  object Input: TEdit
    Left = 8
    Top = 176
    Width = 121
    Height = 21
    Anchors = [akLeft, akRight, akBottom]
    TabOrder = 4
    Text = 'Hallo'
  end
  object ClientSocket1: TClientSocket
    Active = False
    ClientType = ctNonBlocking
    Port = 0
    OnConnect = ClientSocket1Connect
    OnDisconnect = ClientSocket1Disconnect
    OnRead = ClientSocket1Read
    OnError = ClientSocket1Error
    Left = 96
    Top = 96
  end
end

Hier der Quelltext, ebenfalls einfach den Standard-Code in der IDE komplett ersetzen:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
unit Unit1;

interface

uses

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

const
  MY_PORT = 12345// an diesem Port wartet der Server auf Clients

type
  TForm1 = class(TForm)
    ServerAdress: TEdit;
    Online: TCheckBox;
    Log: TMemo;
    Input: TEdit;
    BtnSend: TButton;
    ClientSocket1: TClientSocket;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure OnlineClick(Sender: TObject);
    procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure BtnSendClick(Sender: TObject);
    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// bei Programmstart ausführen
procedure TForm1.FormCreate(Sender: TObject);
begin
  ClientSocket1.Port := MY_PORT; // Port eintragen
end;

// Online-Checkbox wechselt den Status
procedure TForm1.OnlineClick(Sender: TObject);
begin
  if (Online.Checked) then // falls wir online gehen...
    ClientSocket1.Host := ServerAdress.Text; // ...Serveradresse eintragen
  ClientSocket1.Active := Online.Checked; // neuen Status setzen
end;

// Verbindung erfolgt (connect) -> Meldung machen
procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Log.Lines.Add('Verbunden mit '+ServerAdress.Text);
end;

// Verbindung getrennt (disconnect) -> Meldung machen
procedure TForm1.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Log.Lines.Add('Verbindung getrennt.');
  // falls der Server getrennt hat, sonst bleibt der Haken stehen,
  Online.Checked := FALSE; // obwohl wir gar nicht mehr online sind!
end;

// Fehler in der Verbindung aufgetreten
procedure TForm1.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  Log.Lines.Add('Fehler '+IntToStr(ErrorCode));
  Online.Checked := FALSE; // sicherheitshalber Verbindung trennen
  ErrorCode := 0// keine Exception erzeugen, Fehler behandelt
end;

// Sende-Button bearbeiten
procedure TForm1.BtnSendClick(Sender: TObject);
begin
  if (ClientSocket1.Active) then // sind wir online?
    ClientSocket1.Socket.SendText(Input.Text) // ja, Text senden
  else
    Log.Lines.Add('Nicht verbunden!'); // nein, Meldung machen
end;

// Daten vom Server eingetroffen
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
begin
  Log.Lines.Add(Socket.ReceiveText); // lesen und ausgeben
end;

// bei Programmende ausführen
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if (ClientSocket1.Active) then // noch online?
    ClientSocket1.Close; // ja, dann trennen
end;

end.

Erläuterungen zum Code (die konstante Portdefinition kennen wir jetzt schon):

Beim Programmstart tragen wir zunächst nur die Portnummer ein. Die Adresse des Servers brauchen wir erst dann, wenn wir eine Verbindung herstellen wollen. Dazu ist die CheckBox "Online" da, deren OnClick-Ereignis entsprechende Aktionen durchführt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
// Online-Checkbox wechselt den Status
procedure TForm1.OnlineClick(Sender: TObject);

begin
  if (Online.Checked) then // falls wir online gehen...

    ClientSocket1.Host := ServerAdress.Text; // ...Serveradresse eintragen
  ClientSocket1.Active := Online.Checked; // neuen Status setzen
end;

Wenn wir von offline->online wechseln (das fragt die if-Bedingung ab), tragen wir vorher noch die Adresse des Servers ein. Dann weisen wir einfach den Zustand der CheckBox an die .Active-Eigenschaft des ClientSockets zu, so dass entweder eine Verbindung aufgebaut (Haken gesetzt) oder die Verbindung getrennt wird (Haken entfernt).

Wir gehen in unserem Beispiel mal davon aus, dass das Projekt nur auf dem lokalen PC getestet wird. Die eigene IP-Adresse ist immer "127.0.0.1" oder "localhost". Diese (virtuelle) Netzwerkschnittstelle ist auf jedem PC vorhanden und bezeichnet einfach "sich selbst". Deshalb ist "localhost" bereits voreingestellt, damit auch Benutzer ohne LAN das Tutorial auf dem eigenen PC nachvollziehen können. Das Projekt läuft selbstverständlich im LAN (dann die entsprechenden lokalen IP-Adressen verwenden) und ist durchaus auch über das Internet nutzbar. Allerdings braucht man hier dann die öffentliche IP-Adresse des PCs, auf dem das Server-Programm läuft. Diese lässt sich z.B. leicht in einem Browser über die Seite www.whatismyip.com abfragen. Vorsicht Falle: Wenn ein (DSL-)Router im Einsatz ist, dann ist noch ein Portforwarding (heißt auch manchmal "virtual Server") notwendig, sonst können sich Clients aus dem Internet nicht zum Server verbinden. Genaueres kann ich hier nicht allgemeingültig beschreiben, bitte gegebenenfalls im Forum nachfragen bzw. die Suchfunktion benutzen. ;) Nochmal Falle: Wird ein Client auf dem selben PC wie der Server gestartet, bleibt es für diesen Client weiterhin bei "localhost" als Serveradresse (ist ja auch auf dem selben PC)! Nur Clients, die von ausserhalb des LANs eine Verbindung aufbauen wollen, brauchen die öffentliche IP des Routers.

Wenn eine Verbindung aufgebaut werden konnte, tritt das Ereignis OnConnect ein, in dem wir die Verbindung melden.

Wird die Verbindung getrennt, tritt das Ereignis OnDisconnect ein. Auch hier melden wir Entsprechendes, allerdings setzen wir noch zusätzlich die CheckBox zurück, da - falls der Server die Verbindung getrennt hat - der Haken sonst stehen bleiben würde.

Konnte keine Verbindung zum Server hergestellt werden oder tritt in einer Verbindung ein Fehler auf, wird das Ereignis OnError ausgelöst. Wir protokollieren einfach den Fehler mit Nummer, trennen sicherheitshalber die Verbindung (falls das nicht schon geschehen sein sollte -> Haken-Problem) und setzen die Fehlervariable zurück, damit keine Exception ausgelöst wird.

Kommen wir jetzt aber endlich zu den interessanten Prozeduren: Wenn wir einen Text eingegeben haben und diesen nun senden wollen, müssen wir im Button-Ereignishandler nur noch den Text senden:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
// Sende-Button bearbeiten
procedure TForm1.BtnSendClick(Sender: TObject);
begin
  if (ClientSocket1.Active) then // sind wir online?
    ClientSocket1.Socket.SendText(Input.Text) // ja, Text senden
  else
    Log.Lines.Add('Nicht verbunden!'); // nein, Meldung machen
end;

Aber nur dann, wenn auch eine Verbindung besteht (-> if-Abfrage). Haben wir keine Verbindung, gibts nur eine Fehlermeldung, die wir statt dessen ins Protokoll schreiben.

Wenn wir die Textnachricht gesendet haben, erscheint allerdings noch nichts in unserem Protokoll. Das passiert erst dann, wenn der Server die Daten verarbeitet und uns eine entsprechende Nachricht zurückgesendet hat. In diesem Fall tritt das Ereignis OnRead ein, in dem wir die Daten vom Server lesen und ins Protokoll schreiben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
// Daten vom Server eingetroffen
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
begin
  Log.Lines.Add(Socket.ReceiveText); // lesen und ausgeben
end;

Kurz zusammengefasst: Text eintippen -> wird an den Server gesendet -> dieser verteilt die Nachricht an alle Clients -> Nachricht vom Server trifft ein -> ins Protokoll schreiben.

Dieses Konzept nennt man auch Client-Server-Architektur.

Beim Programmende wird natürlich noch eine eventuell bestehende Verbindung getrennt, wir beenden unsere Programme schließlich sauber. ;)

Wer mit diesem Tutorial erfolgreich den Einstieg ins "Netzwerken" geschafft hat und jetzt schon gespannt auf MEHR ist, sollte sich mal das Terminatorzeichen-Protokoll-Tutorial ansehen. Da werden sie geholfen. ;)

cu
Narses


Hinweis zu Delphi-Versionen >=D2009 (Unicode-Problem):
Der Code ist Unicode-Save, es sollte keine Probleme mit Delphi-Versionen >=D2009 geben.

Hinweis zu den Anhängen:
In der Personal-Edition von Delphi stehen die Socket-Komponenten leider nicht in der IDE zur Verfügung (dclsockets70.bpl wird nicht mitgeliefert). Allerdings ist die ScktComp.dcu ja auch bei der Personal-Edition vorhanden, so dass trotzdem (ganz legal!) mit den Socket-Komponenten gearbeitet werden kann, wenn man diese dynamisch erzeugt.
Da die Frage aufgekommen ist, wie man das denn konkret macht, gibt es zur Demonstration der Vorgehensweise die beiden Programme jetzt auch in einer Version, in der der TClientSocket und der TServerSocket dynamisch erzeugt werden.
Einloggen, um Attachments anzusehen!
_________________
There are 10 types of people - those who understand binary and those who don´t.


Zuletzt bearbeitet von Narses am Sa 17.05.14 11:18, insgesamt 25-mal bearbeitet

Für diesen Beitrag haben gedankt: Jakane, Lecaro, Xion
dac424
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Mo 10.07.06 21:23 
Titel: Geile Sache
wie sieht es mit Räume aus die Man erstellen könnte das wäre doch auch nicht übel
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 10.07.06 21:29 
Moin!

Ja, das kann man machen. ;) Dazu brauchst du aber schon ein Protokoll, deshalb solltest du dem entsprechenden Hinweis folgen und dir mal ansehen, wie man sowas umsetzt. Damit dann verschiedene Chat-Räume abzubilden, ist nicht weiter schwer.

Hier in diesem (Super-Simpel-)Beispiel führt das allerdings viel zu weit und hilft nicht beim Verständnis der grundlegenden Probleme.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
dac424
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Mo 10.07.06 23:34 
Titel: Flüstern wäre das
Frage ist es den auch machbar zu flüstern an eine gewisse IP das nur Der Jenige das lesen kann und ev. noch Räume zu erstellen. Das wäre dann genau das PRG was ich bräuchte habe es im moment so wie es ist in meinem Projekt Implementiert und es läuft herfor- ragend.
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 11.07.06 00:09 
Titel: Re: Flüstern wäre das
Moin!

user profile icondac424 hat folgendes geschrieben:
Frage ist es den auch machbar zu flüstern an eine gewisse IP das nur Der Jenige das lesen kann

Ja, das ist bereits im Protokoll-Chat-Tutorial enthalten.

user profile icondac424 hat folgendes geschrieben:
und ev. noch Räume zu erstellen.

Ein Chat-Raum ist doch nix anderes, als eine virtuelle Gruppierung; läßt sich mit einem Protokoll ganz leicht umsetzen. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 12.07.06 23:40 
Moin!

Da die Frage danach aufkam: es gibt die Beispielprogramme jetzt auch in einer Version, bei der die Socket-Komponenten dynamisch erzeugt werden, so dass die Integration der Komponenten in der IDE nicht notwendig ist (Personal-Editions).

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
pupu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 104

WinXP
Borland Delphi 7, Turbo Pascal 7
BeitragVerfasst: Do 13.07.06 13:36 
wenn ich den server starte und dann mit dem client mich unter "localhost" verbinde, und dann das "hallo" abschick, denn dauert das erst ne weile und dann kommt ne Fehlermeldung mit dem Inhalt:

List index out of bounds (1)

hab ich was falsch gemacht? :?

der "chat" funktioniert ja quasi auch über netzwerk, nur dass der der sich verbinden will unter Adresse meine IP eingibt, weil bei mir der Server liegt oder irre ich mich da?
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 13.07.06 14:08 
Moin!

user profile iconpupu hat folgendes geschrieben:
wenn ich den server starte und dann mit dem client mich unter "localhost" verbinde, und dann das "hallo" abschick, denn dauert das erst ne weile und dann kommt ne Fehlermeldung mit dem Inhalt:
ausblenden Quelltext
1:
List index out of bounds (1)					

hab ich was falsch gemacht? :?

Kommt der Fehler bei meinen fertigen EXEcutables oder bei der von dir erstellten Version davon? Wenn ich das mit den EXEs probiere, klapp´s bei mir einwandfrei (bei anderen auch).

Wenn es mit meinen Programmen geht, aber mit deiner Version davon nicht, dann solltest du mal den Quelltext zeigen, weil sonst kommen wir nicht weiter. ;)

user profile iconpupu hat folgendes geschrieben:
der "chat" funktioniert ja quasi auch über netzwerk, nur dass der der sich verbinden will unter Adresse meine IP eingibt, weil bei mir der Server liegt oder irre ich mich da?

Ich unterstelle mal, du meinst mit "Netzwerk" eine Internetverbindung. ;) Ja, das ist korrekt; wie aber weiter oben im Tutorial-Text schon erwähnt, ist bei einem Router für den Serverdienst noch ein Portforwarding notwendig.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
dac424
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Fr 14.07.06 08:25 
Titel: Flüstern und Chaträume
wäre nicht schlecht wenn man die version mit flustern und Räume haben könnte als source
würde mich über PN freuen, wo die Source bei ist.
dac424
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Fr 14.07.06 08:32 
Titel: Internet
also bei mir läuft die einband frei im Internet man solte jedoch den Port ändern 12345 ist nicht so optimal ich habe 6786 gemacht und dem entsprechen im Router frei gegeben zu dem rechner wo der Server läuft
es wäre auch nicht schlecht eine Art bann funktion wo man IP´s bzw eine funktion ausbauen könnte das man jemanden sperren kann sprich jeder client hat eine nummer
die man im server sperren kan.

Client instaliert 1 Start client vbekommt eine nummer die immer gleich bleibt.
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 14.07.06 09:17 
Moin!

Mein lieber user profile icondac424, das hier ist die super-simpel-Version für Einsteiger. ;)

Es macht einfach keinen Sinn, hier noch weitere Funktionen reinzustopfen, noch dazu, wenn dafür ein Protokoll notwendig ist. Ich habe dir weiter oben bereits einen Hinweis auf mein Protokoll-Chat-Tutorial gegeben, da wird auch lang und breit erklärt, wie man eine Flüstern-Funktion umsetzt. Chat-Räume sind eine weitere, mögliche Erweiterung, die du leicht selbst umsetzen kannst, wenn du erstmal den Grundgedanken eines Protokolls verstanden hast.

Bitte also hier nicht weiter nach neuen Funktionen fragen, da ich das an dieser Stelle nicht umsetzen werde, um den Charakter dieses Tutorials ("für Einsteiger") nicht kaputt zu machen.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
pupu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 104

WinXP
Borland Delphi 7, Turbo Pascal 7
BeitragVerfasst: Sa 15.07.06 10:50 
ne ich meinte netzwerk...wenn ich z.b. mit meinem bruder nebenan chatten will oder so
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 15.07.06 22:24 
Moin!

user profile iconpupu hat folgendes geschrieben:
ne ich meinte netzwerk...wenn ich z.b. mit meinem bruder nebenan chatten will oder so

Ja, klar geht das. ;)

Was ist nun mit deinem Laufzeitproblem? Gefunden?

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
dac424
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Sa 15.07.06 23:47 
Titel: also wenn ich das Richtig verstanden habe.
Versuche mir das jetzt mal bildlich um zusetzen
dann entscheidet der Server jetzt was an die Clients gesendet wird ?
ausblenden Delphi-Quelltext
1:
MyMessage := Socket.RemoteAddress+': '+Socket.ReceiveText; //original					


ich köntte doch den String erweitern oder??

ausblenden Delphi-Quelltext
1:
MyMessage := Socket.RemoteAddress+': '+Socket.ReceiveText+Raum+Sperrung;					


sollte jetzt die IP im Server eingetragen sein beispielsweise in einer Memo dann

könnte ich das Auswerten und bei dem Client eine unsichtbare checkbox aktivieren?

und wenn ich das Programm beende wird diese in der Registri eingetragen so wie ich auch die Serverdarten Eintrage!

starte ich das Program erneut ist die Checkbox immer noch gesetzt und der Client ist gesperrt, er bekommt zwar daten aber diese werden nicht in der Logausgabe gezeigt?

Moderiert von user profile iconjasocul: Delphi-Tags hinzugefügt
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 15.07.06 23:57 
user profile iconNarses hat folgendes geschrieben:
Mein lieber user profile icondac424, das hier ist die super-simpel-Version für Einsteiger. ;)

Es macht einfach keinen Sinn, hier noch weitere Funktionen reinzustopfen, noch dazu, wenn dafür ein Protokoll notwendig ist. Ich habe dir weiter oben bereits einen Hinweis auf mein Protokoll-Chat-Tutorial gegeben


user profile iconNarses hat folgendes geschrieben:
Bitte also hier nicht weiter nach neuen Funktionen fragen, da ich das an dieser Stelle nicht umsetzen werde


Wenn du Kenntnis des Protokoll-Chats zeigst und im entsprechenden Thread fragst, würde ich mir überlegen, ob ich dir dann dabei weiterhelfe.

Hier passiert in dieser Richtung jedenfalls nix.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
pupu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 104

WinXP
Borland Delphi 7, Turbo Pascal 7
BeitragVerfasst: So 16.07.06 18:34 
hier ma n screenshot, damit ihr euch das vielleicht etwas besser vorstellen könnt was genau passiert...vllt hilft das ja :wink:

Moderiert von user profile iconTino: Bild als Dateianhang hochgeladen.

edit: habs so weit gelöst...aus irgendeinem Grund hatte ich aus:
ausblenden Delphi-Quelltext
1:
2:
3:
// und an alle verbundenen Clients senden
  for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
    ServerSocket1.Socket.Connections[i].SendText(MyMessage);

ein:
ausblenden Delphi-Quelltext
1:
2:
3:
 // und an alle verbundenen Clients senden
  for i := 1 to ServerSocket1.Socket.ActiveConnections do
    ServerSocket1.Socket.Connections[i].SendText(MyMessage);


gemacht...wahrscheinlich zur Verständlichkeit :wink:
Einloggen, um Attachments anzusehen!
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 13.09.06 16:17 
Moin!

Es gibt jetzt auch eine Offline-Version des Tutorials als PDF im Anhang zum Download (wie immer, im ersten Beitrag). ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Memorius
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 25

Windows XP Professional
Delphi 4.0 PE
BeitragVerfasst: Sa 02.06.07 22:05 
Hallo!
Ich wollte mal fragen, ob es geht dass uch die IP-Adresse eines Servers auch übers Internet herausfinden kann, ohne bei dem, der den Server laufen hat anrufen zu müssen? Also, wenn viele Leute das Programm (oder besser: beide Programme) hat und eder nach belieben einen Server öffnen kann, geht es dann dass man diese Server im I-Net suchen und sich anzeigen lassen kann?
(ich hoffe diese frage wurde noch nicht beantwortet und ich habe sie einlicherweise übersehehn :?!?: )
ich weiß, das geht auch über das Mini-tutorial hinaus... aber BITTE!!!!! :flehan:

-Memorius-
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10122
Erhaltene Danke: 1227

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 03.06.07 13:35 
Moin!

user profile iconMemorius hat folgendes geschrieben:
Ich wollte mal fragen, ob es geht dass uch die IP-Adresse eines Servers auch übers Internet herausfinden kann, ohne bei dem, der den Server laufen hat anrufen zu müssen?

Ja, klar geht das (s.u., allerdings evtl. nicht so, wie du möchtest). ;)

user profile iconMemorius hat folgendes geschrieben:
Also, wenn viele Leute das Programm (oder besser: beide Programme) hat und eder nach belieben einen Server öffnen kann, geht es dann dass man diese Server im I-Net suchen und sich anzeigen lassen kann?

Nein, sowas geht nur, wenn ein fester Server im Internet die Vermittlung übernimmt. :?

Aber du kannst deinem PC einen dynamischen DNS-Alias verpassen, dann kann man diesen über den Namen (z.B. MyPC.dyndns.org) ansprechen, ohne die IP-Adresse zu kennen. :idea: ;)

Einfach mal hier ein bischen nach Suche in: Delphi-Forum DYNDNS suchen, dann auf der DynDNS-Homepage registrieren (www.dyndns.org, 5 Hosts sind für private Anwendung kostenlos) und loslegen. :D

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Memorius
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 25

Windows XP Professional
Delphi 4.0 PE
BeitragVerfasst: So 03.06.07 14:16 
Danke!!!