Autor Beitrag
Sithlord
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 172



BeitragVerfasst: Mo 28.12.09 15:03 
Hallo Mitglieder,

bin grad dabei ein kleines Server/Client Programm zu schreiben. Nun sendet z.b. ein Client einen Befehl zum Server, der diesen dann veranlagt, an einen bestimmten Clienten etwas zu senden. Von jedem angemeldeten Clienten habe ich die eindeutige IP Adresse in einer Listbox gespeichert.

Meine Frage:
Wie veranlasse ich den Server, nur an den einen Clienten einen Befehl zu schreiben - die anderen Clienten müssen aber verbunden bleiben.

Mfg Sithlord

Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Mo 28.12.09 15:51 
Du hast ne wichtige Info vergessen:
Mit welcher Komponente arbeitest du? Indy? Wenn ja, welche Version? Oder die normalen Server und ClientSocket ?

_________________
PROGRAMMER: A device for converting coffee into software.
Astat
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 75
Erhaltene Danke: 1

Windows 2000
D6, D7, D2007, Lazarus
BeitragVerfasst: Mo 28.12.09 16:07 
user profile iconSithlord hat folgendes geschrieben Zum zitierten Posting springen:
..
Von jedem angemeldeten Clienten habe ich die eindeutige IP Adresse in einer Listbox gespeichert.

Meine Frage:
Wie veranlasse ich den Server, nur an den einen Clienten einen Befehl zu schreiben - die anderen Clienten müssen aber verbunden bleiben.

Mfg Sithlord


Hallo Sithlord, den Client kannst Du immer durch den zugehörigen Socket identiffizieren. D.h. "Socket" ist für einen Client immer eindeutig.
Bei Verwendung einer IP, bekommst Du Probleme, wenn mehrere Netzwerkkarten, WLan, PPP-Adapter etc. aktiv sind, und die Ermittlung der IP somit nicht immer eindeutig ist.
Um dieses Problem zu beheben, speichere Dir in jedem Connect ein Object, bzw. Record etc. mit den übermittelten Clientinfos, eine GUID ist dafür gut geeignet, in einer schnellen Hash Liste. Bei jeder Anfrage eines Clients durchsuchst Du die Liste mit dem Socket als ID und bekommst dann das vorher gespeicherte Clientobject zurück.
An einen bestimmten Client kannst Du einfach mit dem Socket zurückschreiben.
Durchsuche die Hashliste nach deinen gewünschten Parametern (IP, Rechnername, MAC, Username etc.), ermittle den Socket, und Sende die Daten mit, send(Socket,..) bei Verwendung der Socket-API, oder bei Verwendung in Komponenten meist soetwas wie Socket.Send... an den Client.

Beschriebenes Szenario funktioniert natürlich nur wenn die Sockets permanent verbunden sind.


lg. Astat

Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Sithlord Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 172



BeitragVerfasst: Mo 28.12.09 16:50 
So in etwa wollte ich das auch haben, super Idee,

es gibt nun noch ein problem: Was muss ich vom Socket den speichern lassen - damit der socket weiß an welchen Client er das schicken muss.
Oder wie veranlasse ich es, das der Socket das dann an den Clienten schreibt - muss ja bestimmt eine eindeutige Identifizierung irgendwo vorliegen...

Oh sehe es erst jetzt, die Tclient und Tserver - die stinknormalen VCL Socket komponenten von Delhpi7
Astat
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 75
Erhaltene Danke: 1

Windows 2000
D6, D7, D2007, Lazarus
BeitragVerfasst: Mo 28.12.09 17:25 
user profile iconSithlord hat folgendes geschrieben Zum zitierten Posting springen:
So in etwa wollte ich das auch haben, super Idee,

es gibt nun noch ein problem: Was muss ich vom Socket den speichern lassen - damit der socket weiß an welchen Client er das schicken muss.
Oder wie veranlasse ich es, das der Socket das dann an den Clienten schreibt - muss ja bestimmt eine eindeutige Identifizierung irgendwo vorliegen...


Hallo Sithlord, ich gehe mal von einer Asynchronen Socketverbindung aus.

Du musst den Client-Socket, oder das ClientObject, bei Verwendung einer Komponente, speichern, den Du im Connect Event bekommst. Mit diesem Socket (Object) kannst Du dann zu jeder Zeit an einen Client Daten zurückschicken.

PS: Zeig mal den Source, dann kann gezielter geholfen werden.

lg. Astat
Sithlord Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 172



BeitragVerfasst: Mo 28.12.09 18:52 
Hier, wollte das ein User dem anderen einen Text senden kann, der Code ist vom Server. Ich habe aber nicht gefunden was ich da speochern muss vom Sender:TObject ?

Mfg Sithlord

Hier mal der Code von der Komponente:
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:
procedure TForm1.serverClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
remoteip:string;
begin
remoteip:= socket.RemoteAddress;
sender.
listbox1.Items.Add('Client '+remoteip+ ' verbunden');
end;

procedure TForm1.serverClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
remoteip:string;
i:integer;
begin
remoteip:=socket.RemoteAddress;
listbox1.Items.Add('Client '+socket.RemoteAddress+' getrennt');
for i := 0 to Listbox2.items.count - 1 do begin
  if Pos(remoteip, ListBox2.Items[i]) > 0 then
    listbox2.Items.Delete(i);
  end;
end;
procedure TForm1.serverClientWrite(Sender: TObject;
  Socket: TCustomWinSocket);
var
received:string;
received2:string;
remoteip:string;
A: TStringList;
LABEL sendpong;
LABEL sendtext;
LABEL ende;
begin
A := TStringList.Create;
received:=socket.ReceiveText;
Split('|', received, A) ;
received2:=A[0];
remoteip:=socket.RemoteAddress;
listbox1.Items.Add('Befehl: '+received);
if (received='ping'then GOTO sendpong
else
if (received='sendtext'then GOTO sendtext
else
GOTO ende;
//Pong senden um zu sagen das der Server aktiv ist ;)
sendpong:
listbox1.Items.Add('Ping von ' +remoteip+ ' bekommen');
socket.SendText('pong');
listbox1.Items.Add('Pong an ' +remoteip+ ' gesendet');
//User in die Userliste adden:
listbox1.Items.Add(remoteip+' ist nun angemeldet!');
listbox2.Items.Add(remoteip);
GOTO ende;
//Sendtext - damit können sich User kleine Texte senden ^^
sendtext:
GOTO ende;
//Das Ende
ende:
A.Free;
end;


---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

Im Prinzip ist es ja aufgebaut wie "flüstern" beim Chatten. Ich find bloß grad das Tutorial für einen Delphi Chat, worin man flüstern konnte, nicht mehr ;)
Wäre sehr nett wenn den jemand auftreibt ^^


Edit:

Hab nun herausgefunden, es gibt dieses Socket.activeconnetions - wird verwendet um jeden Clienten was zu schicken, wenn ich jetzt wüsste, welcher Integer der grad neu verbundene Client hat - wäre alles perfekt gelöst ;)

Mfg SIthlord
Astat
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 75
Erhaltene Danke: 1

Windows 2000
D6, D7, D2007, Lazarus
BeitragVerfasst: Mo 28.12.09 23:12 
Hallo Sithlord, anbei ein Demo wie das gemacht werden kann.

Bei dem Demo ist noch kein Empfanhsbuffer für jeden verbundenen Client, und auch noch kein Protokoll implementiert.

Solltest Du noch weitere Hilfe brauchen, einfach Melden.

lg. Astat
Einloggen, um Attachments anzusehen!
Sithlord Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 172



BeitragVerfasst: Mo 28.12.09 23:22 
Vielen, vielen Dank ;)

Aber ich steige da nicht so sehr ganz durch, sorry.
Mache dies ja alles nur Hobbymäßig und belese mich da schon ne Menge.
Ich hätte da auch noch einen Ansatz:
Es gibt ja bei diesen Komponenten dieses "Activeconnetions".
Demnach müsste jeder verbundene Client einen eindeutigen Integerwert haben.
Diesen würde ich in einer Listbox abspeichern und bei bedarf abrufen ;)
Wie find ich diesen Wert raus?
Bsp:
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);

Oder was ist eig. dieses Sockethandle - ist das auch bei jedem einzigartig oder
wie soll ich den Quelltext von dir verstehen?

Mfg Sithlord
Astat
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 75
Erhaltene Danke: 1

Windows 2000
D6, D7, D2007, Lazarus
BeitragVerfasst: Di 29.12.09 00:46 
Moderiert von user profile iconNarses: Komplett-Zitat des letzten Beitrags entfernt.

Hallo Sithlord, ServerSocket1.Socket.Connections[i] liefert das TCustomWinSocket Object zurück.
ServerSocket1.Socket.Connections[i].SocketHandle liefert das "SocketAPI" Socket Handle.
Beide sind immer für einen Client eindeutig, wobei ein IntToStr(ServerSocket1.Socket.Connections[i].SocketHandle) am einfachsten zu handhaben ist.
Das Sockethandle habe ich nur verwendet um das zugehörige Clientobjekt in der Listbox zu suchen.
Im Hinterkopf hatte ich da eine spätere Object suche, nach einem Integer (Sockethandle), aus einer Hashlist.
Du kannst natürlich auch direkt das TCustomWinSocket Object verwenden.

lg. Astat
Sithlord Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 172



BeitragVerfasst: Di 29.12.09 01:29 
Vielen Dank,
damit bleibt für mich nur noch als letzte Frage woher ich das i wissen kann - vl. stelle ich mich dabei auch doof an aber der erste Client bekomm ja 0, der zweite 1 usw. Aber was ist wenn der dritte geht - wird diese Lücke aufgefüllt oder nicht.

Mfg Sithlord

P.S. Vielen Dank für deine Hilfe, hast alle deine ersten Posts an meinem Problem verschwendet ^^
Astat
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 75
Erhaltene Danke: 1

Windows 2000
D6, D7, D2007, Lazarus
BeitragVerfasst: Di 29.12.09 06:35 
Moderiert von user profile iconNarses: Komplett-Zitat des letzten Beitrags entfernt.

Hallo Sithlord, die Komponente aktualisiert automatisch die Interne Connection Liste. D.h. Wenn ein Disconnect und oder Socket Error ausgelöst wird, wird der Socket, der das verursacht, automatisch aus der Liste entfernt. Also die Lücke wird nicht ausgefüllt, sondern es wird diese entfernt. Alle nachfolgenden Einträge rücken nach, und bekommen somit um ActIndex -1, einen neuen index.
Beispiel: 1, 2, 3, 4, 5 sind vorhanden, dann wird 3 entfernt, somit werden alle > 3 um eins decrementiert 4 wird zu 3, 5 wird zu 4 usw.

Tip:
Auf Grund dieses Verhaltens, solltest Du die Schleife wo du Daten an die Client sendest, mit for i := LisBox1.items.count -1 downto 0 do .. aufbauen. Denn wenn währen des Sendens sich ein Client Disconnectet, kommt es nicht zu einer Indexverletzung.

lg. Astat

Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 02.01.10 02:32 
Moin!

user profile iconSithlord hat folgendes geschrieben Zum zitierten Posting springen:
Im Prinzip ist es ja aufgebaut wie "flüstern" beim Chatten. Ich find bloß grad das Tutorial für einen Delphi Chat, worin man flüstern konnte, nicht mehr ;)
Wäre sehr nett wenn den jemand auftreibt
Falls du das hier gemeint hast? ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Astat
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 75
Erhaltene Danke: 1

Windows 2000
D6, D7, D2007, Lazarus
BeitragVerfasst: Sa 02.01.10 06:41 
user profile iconNarses
www.delphi-library.d...kets+v400_54269.html


Hallo Narses, muss schon sagen, Hut ab!! Ist eine wahnsinns Doku und Source!! Respekt!!

lg. Astat