Autor Beitrag
maxda
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Sa 30.05.09 15:36 
Hallo an alle,
ich habe vor kurzem mit Delphi angefangen, habe aber auch schon in andersn Sprachen programmiert. Nun wollte ich als erstes Programm einen Chat basteln. Dazu sind die Sockets am geeignetsten. Also habe ich das hier geschrieben:

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:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
unit Unit3;

interface

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

type
  TForm3 = class(TForm)
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Edit3: TEdit;
    Button2: TButton;
    GroupBox3: TGroupBox;
    Memo1: TMemo;
    Edit4: TEdit;
    Button3: TButton;
    ClientSocket1: TClientSocket;
    ServerSocket1: TServerSocket;
    GroupBox4: TGroupBox;
    Button4: TButton;
    Button5: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure ClientSocket1Onread(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerSocket1Onread(Sender: TObject; Socket: TCustomWinSocket);
    procedure Edit1OnKeyPress(Sender: TObject; var Key: Char);
    procedure Edit3OnKeyPress(Sender: TObject; var Key: Char);
    procedure Edit2OnKeyPress(Sender: TObject; var Key: Char);
    procedure Button5Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Form3OnClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}


procedure TForm3.Button1Click(Sender: TObject);
begin
try
  form3.caption := 'Server';  // Daran sieht man, ob man Server ist

  ServerSocket1.Port:=StrToInt (Edit1.Text); // wählt den Port aus

  ServerSocket1.Open; // Öffnet den Server

  Memo1.Lines.Add('Chatroom (Server) erfolgreich erstellt.');
except
  Memo1.Lines.Add('Fehler beim erstellen eines Chatrooms (Server)!');
end;
end;

procedure TForm3.Button2Click(Sender: TObject);
begin
  try
    form3.Caption := 'Client';  // Daran sieht man, ob man Client ist

    ClientSocket1.Port:=StrToInt (edit3.Text); //Wählt Port aus

    ClientSocket1.Host:=edit2.Text; // Setzt die Ip-Adresse des Servers

    ClientSocket1.open; // Verbindet den Clienten mit dem Server

    Button3.Enabled:=true;
    ClientSocket1.Socket.SendText('c: Client tritt bei');// Sendet Nachricht, dass der Client sich verbunden hat

    Memo1.Lines.Add('Verbindung zum Server wurde hergestellt.');
  except
    Memo1.Lines.Add('Fehler beim Verbinden mit dem Server!');
  end;
end;

procedure TForm3.Button3Click(Sender: TObject);
begin
  if form3.caption='Server' then
  begin
    if Serversocket1.Socket.ActiveConnections=1 then //wenn ein Client da ist,...

    begin
      try
        Memo1.lines.add('Server:'+edit4.text); //fügt den eigenen Text ins Memo

        serversocket1.Socket.Connections[0].SendText(edit4.text);  //Sendet an den Clienten die Nachricht aus Edit1

      except
        Memo1.Lines.Add('Fehler beim Senden einer Nachricht an den Client!');
      end;
    end
  else
  begin
    Memo1.lines.add('Es ist noch kein Client/Chatpartner da.'); //sonst wird die Fehlermeldung ins Memo eingefügt

    Edit4.text:=''// Sende-Feld leeren

  end;

  if form3.caption='Client' then
  begin
    if Clientsocket1.Active=true then // Wenn man mit einem Server erfolgreich verbunden worden ist,...

    begin
      try
        Memo1.lines.add('Client:'+edit4.text); // wird der eigenen Text ins Memo eingefügt

        clientsocket1.Socket.SendText('n:'+edit4.text);  //n: signalisiert dem Server, dass es eine Nachricht vom Nutzer ist.

      except
        Memo1.Lines.Add('Fehler beim Senden einer Nachricht an den Server!');
      end;
    end
    else
    begin
      Memo1.lines.add('Du bist mit keinem Server verbunden.'); //fügt Fehlermeldung ins Hauptfeld

    end;
  end;
  Edit4.text:=''// Sende-Feld leeren

  end// Ende des Client-Abschnitts

end;

procedure TForm3.Button4Click(Sender: TObject);
begin
  if form3.caption='Client' then // Wenn es ein Client ist,...

  begin
    try
      Clientsocket1.Close; // Client schließen

      memo1.Lines.add('Verbindung geschlossen');
    except
      memo1.Lines.Add('Fehler beim Schließen der Verbindung!');
    end;
  end;

  if form3.caption='Server' then // Wenn es ein Server ist,...

  begin
    try
      Serversocket1.Close; // Server schließen

      memo1.Lines.add('Server (Chatroom) geschlossen');
    except
      memo1.Lines.Add('Fehler beim Schließen des Servers!');
    end;
  end;
  Form3.Caption:='Simple TCP Chat'// Und Caption wirder zum Ursprung zurücksetzen

end;

procedure TForm3.Button5Click(Sender: TObject);
begin
   // Hilfe ausgeben

  memo1.Lines.Add('HILFE:');
  memo1.Lines.Add('');
  memo1.Lines.Add('Wenn man einen neuen Chat erstellen will, muss man einen Port angeben.');
  memo1.Lines.Add('Ein Port ist sozusagen ein Anschluss am PC.');
  memo1.Lines.Add('Man sollte dort eine Zahl über 1024 angeben, aber es kommt immer auf den Computer/Server an, welche Ports frei sind.');
  memo1.Lines.Add('');
  memo1.Lines.Add('Wenn man sich mit einem Vorhanden Server, also mit einem vorhandenen Chat, verbinden will, muss man die IP und den Port des anderen Nutzer eingeben.');
  memo1.Lines.Add('Es kann sich (bis jetzt) immer nur ein Client mit einem Chat verbinden.');
end;

procedure TForm3.ClientSocket1Onread(Sender: TObject; Socket: TCustomWinSocket);
begin
  memo1.Lines.Add('Server:' + socket.receivetext);  //Fügt dem Memo die Nachricht hinzu

end;[/color]


procedure TForm3.Edit1OnKeyPress(Sender: TObject; var Key: Char);
// lässt nur Zahlen und die Backspacetaste zu (Port-Host)

begin
  if NOT (Key in [#8'0'..'9']) then
    Key := #0;
end;


procedure TForm3.Edit2OnKeyPress(Sender: TObject; var Key: Char);
// lässt nur Zahlen, Punkte und die Backspacetaste zu (IP)

begin
  if NOT (Key in [#8'0'..'9''.']) then
    Key := #0;
end;

procedure TForm3.Edit3OnKeyPress(Sender: TObject; var Key: Char);
// lässt nur Zahlen und die Backspacetaste zu (Port)

begin
  if NOT (Key in [#8'0'..'9']) then
    Key := #0;
end;

procedure TForm3.Form3OnClose(Sender: TObject; var Action: TCloseAction);
begin
  if form3.caption='Client' then // Wenn es ein Client ist,...

  begin
    Clientsocket1.Close; // Client schließen

  end;

  if form3.caption='Server' then // Wenn es ein Server ist,...

  begin
    ServerSocket1.Close; //  Sever schließen

  end;
end;

procedure TForm3.ServerSocket1Onread(Sender: TObject; Socket: TCustomWinSocket);
var text: string;
begin
  text:=Socket.ReceiveText;
  if text='c: Client tritt bei' then //Wenn der Client sich einloggt und die Nachricht geschickt hat,...

  begin
    memo1.Lines.Add('Client hat sich verbunden.');// wird das angezeigt.

    Button3.Enabled:=true; //sende button kann jetzt gedrückt werden

  end
  else
  begin
    Delete(text, 12);
    memo1.Lines.Add('Client:' + text); //wenn es eine Nachticht vom Nutzer ist, wird dem Memo die Nachricht hinzugefügt

  end
end;

end.


So, wenn ich auf meinem Computer einen Server erstelle funktioniert das Prima, jetzt gibt es aber folgende(s) Problem(e):
1. Ich muss den 'Verbinden Button' zweimal anklicken, damit eine Nachricht am Server ankommt (siehe Z.79). In das Memo-Feld vom Client wird (logischerweise) schon eine 'Erfolgs-Meldung' geschrieben.
2. Der Server kann zwar an den Client etwas senden, aber der Client nicht an den Server. Noch nicht mal das Edit wird geleert! Vielleicht ist Clientsocket1.Active<>true ??? Aber dann würde ja wenigstens das Edit-Feld geleert werden. Also müsste ja caption <> 'Client', aber das wird ja dann dazu gesetzt!

Was mache ich falsch? Wo liegt der Fehler?
Ich hoffe ihr könnt mir helfen.
Viele Grüße, maxda

Edit: Hier nochmal eine Liste:
Button1: Server Erstellen
Button2: Client erstellen
Button3: Text senden
Button4: Verbindung schließen
Button5: Hilfe aufrufen
Edit1: Server - Port
Edit2: Client - IP
Edit3: Client - Port
Edit4: Sende-Feld

Das erste Problem ist jetzt gelöst - es muss ins das senden der Nachricht an den Server muss ins OnConnect Ereigniss, aber das 2. ist immer noch aktuell.
2. Problem ist jetzt auch gelöst (end; war an der falschen stelle).
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 31.05.09 12:23 
Moin und :welcome: im Forum!

Du hast mindestens ein großes Problem in deinem Ansatz:
user profile iconmaxda hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm3.ServerSocket1Onread(Sender: TObject; Socket: TCustomWinSocket);
var text: string;
begin
  text:=Socket.ReceiveText;
  if text='c: Client tritt bei' then //Wenn der Client sich einloggt und die Nachricht geschickt hat,...
Du verlässt dich auf die Ereignisse zum Trennen der Datenpakete. Das ist im Allgemeinen ein Fehler, der dir später sehr viel Ärger machen wird. :? Hier ist ein FAQ-Beitrag, der detailiert erläutert, warum das so ist und wie man das Problem lösen kann. :les: :think: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
maxda Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: So 31.05.09 14:34 
Ja, danke für den Hinweis, aber bei einem kleinen Chat, der nur für 2 Personen gedacht ist, werde ich das erstmal so lassen. Nun habe ich aber ein anderes Problem:
Wenn ich das im Netzwerk ausprobier dann findet der Client den Server nicht (ich habe es über die öffentlich und über die interne IP versucht). Auf wenn ich das Programm auf meinem PC 2* mal öffne und die Prozesse mit localhost miteinander verbinde klappt es, über das Internet habe ich es noch nicht ausprobiert, aber das Netzwerk in dem ich es ausprobiert habe hat internet-anschluss.