![]() |
Server disconnectet Client
hallo dp,
wiedermal ein socket-problem: diesmal möchte ich vom server aus einzelne Clienten disconnecten. beim connecten eines clienten werden die clienten-daten in ein listbox geladen:
Code:
nun möchte ich das man ein item der listbox anklickt, dann auf den 'disconnect' button geht und die
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket); var ib : integer; begin Memo1.Lines.Add(timetostr(now)+' Neuer User betritt den Chat !'); edit10.text := 'User eingeloggt: ' + IntToStr(ServerSocket1.Socket.ActiveConnections); listbox1.Clear; for ib := 0 to Serversocket1.Socket.ActiveConnections - 1 do listbox1.Items.Add(serversocket1.Socket.Connections[ib].RemoteHost + ' ' + serversocket1.Socket.Connections[ib].remoteaddress); end; verbindung zu diesem clienten getrennt wird. oder eigentlich würde mir auch schon 'normaler' Code (ohne listbox) helfen. ;) bisher habe ich folgendes versucht:
Code:
beides funzt aber net !
procedure button1click;
begin serversocket1.socket.connections[0].disconnect(1); // oder das: serversocket1.socket.connections[1].disconnect(1); end; die delphi hilfe konnte mir nicht helfen und aus google wurde ich auch net schlau ! :roll: Frohe Weihnachten ! |
Re: Server disconnectet Client
Moin!
1. Warum löscht bei einem einzelnen Connect eines neuen Clients gleich die Listbox? Warum fügst du nicht einfach den Client der Listbox hinten an? 2. Warum nutzt du nicht die AddObject() Methode von TStrings und fügst den ServerSocket1ClientConnect() übergebenen Socket einfach mit an den Eintrag mit an? Dieser ist immer eindeutig zu der Connection. 3. Mit dem Vorschlag aus 2. wird es beim ServerSocket1ClientDisconnect() einfacher, weil du dann in dem Objects[] Array nachschauen kannst nach dem Socket der sich verabschiedet hat und somit nur noch den einen Eintrag löschen musst bei der ListBox 4. Und mit dem Vorschlag aus 2. wird deine eigentliche Frage (disconnecten eines gewählten Clients) auch einfach lösbar: Den Socket wieder aus dem Objects[] Array der ListBox rausholen, zu einem TCustomWinSocket casten und einfach seine Methdoe Close() aufrufen. Fertig ist die Suppe... MfG Muetze1 |
Re: Server disconnectet Client
Hallo,
Zitat:
aktiven connections wieder rein ! :roll: (Not macht wohl erfinderisch !) Zitat:
Zitat:
Zitat:
|
Re: Server disconnectet Client
Moin!
Zitat:
Delphi-Quellcode:
Procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
Var lTemp : String; Begin Memo1.Lines.Add(timetostr(now)+' Neuer User betritt den Chat !'); edit10.text := 'User eingeloggt: ' + IntToStr(ServerSocket1.Socket.ActiveConnections); // die oben übergebene Instanz "Socket" ist der neu angelegte Socket der für diesen neuen Client // angelegt wurde bzw. dessen Connection verwaltet. Daher können wir von ihm direkt die benötigten // Informationen wie RemoteHost etc abfragen. Ich habe hier mal eine temporäre lokale Variable lTemp // angelegt für den String der in ListBox erscheint. // Beim AddObject() kannst du ein Object mit angeben was dann zu dem Eintrag mit verwaltet wird. Wenn // du also mit Delete einen Eintrag löscht, dann fliegt dieses gleich mit raus. Daher hast du immer // zu jedem Eintrag den Socket und kannst z.B. wenn der Nutzer einen Eintrag in der ListBox ausgewählt // hat auch direkt diesem Client was schicken - einfach aus ListBox1.Items.Objects[] das Objekt rausholen // und zu einem TCustomWinSocket typecasten. lTemp := Socket.RemoteHost + ' ' + Socket.RemoteAddress; ListBox1.Items.AddObject(lTemp, Socket); End; Zitat:
Delphi-Quellcode:
Procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
Var i : Integer; Begin // Socket ist eindeutig, daher haben wir durch das Connect schon diesen Socket auch in der ListBox. // Also: ListBox1.Items.Objects[] durchgehen, schauen wo dieser übergebene Socket ist und dann den // Eintrag löschen. Fertig! Memo1.Lines.Add(timetostr(now)+' User verlässt den Chat !'); edit10.text := 'User eingeloggt: ' + IntToStr(ServerSocket1.Socket.ActiveConnections-1); // noch ist ActiveConnections nicht aktuell! For i := 0 To ListBox1.Items.Count-1 Do Begin If ( ListBox1.Items.Objects[i] = Socket ) Then Begin ListBox1.Items.Delete(i); Break; End; End; End; Zitat:
Delphi-Quellcode:
Voraussetzung für alle von mir hier dargelegten Posts ist es, dass MultiSelection ausgeschaltet ist bei der ListBox!
Procedure TForm1.Button1Click(Sender: TObject);
Var lSocket : TCustomWinSocket; Begin // wenn ein Eintrag ausgewählt ist... If ( ListBox1.ItemIndex > -1 ) Then Begin // dann den mit AddObject() hinzugefügten Socket mal rausholen lSocket := ListBox1.Items.Objects[ ListBox1.ItemIndex ] As TCustomWinSocket; // ... und dann einfach den Socket schliessen lSocket.Close; End; End; MfG Muetze1 |
Re: Server disconnectet Client
Ich danke dir erstmal ;)
Ich teste das morgen mal aus ! |
Re: Server disconnectet Client
hallo muetze1,
vielen dank für deine hilfe funzt alles wunderbar ;) warum bin ich da nicht selber drauf gekommen ? :mrgreen: jetzt hab ich nur ( :roll: ) noch ein problem: da alle clienten dann in der listbox abgespeichert werden, steht da ja der host und die ip. wenn nun aber mehrere clienten eingeloggt sind, weiß ich dann nicht mehr welcher listbox-eintrag (also ip + host) nun zu welchem user gehört ! deshalb habe ich versucht den nicknamen mit in die listbox zu speichern: Im ClientConnect steht:
Code:
Nachricht setzt sich aus dem Nicknamen (den der User eingibt) und 'hat den Raum betreten' zusammen.
ClientSocket1.Socket.SendText(xorstring(nachricht, ''));
Da der Nickname eh nur 6 Zeichen haben darf, hab ich ihn wie folgt ausgelesen:
Code:
nun hab ich zwar den nicknamen im serverprogramm, doch wie bekomm ich den nun zu dem entsprechenden
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var Texta, encode : string; begin texta := Socket.ReceiveText; nick := xorstring(texta, ''); nick:=Copy(nick, 1, 6); showmessage(nick); end; host + ip eintrag in die listbox ?? hab schon versucht das mit bei OnClientConnect einzubauen, aber da ClientRead ja erst nach OnClientConnect ausgeführt wird, funzt das net ! |
Re: Server disconnectet Client
Moin!
Richtig, beim ClientConnect gibt es noch keine Kommunikation und der Client kann daher nur danach seinen Nick schicken. Daher musst du das nachträglich zuordnen. Erstmal aber nochwas zwischendurch: Die ListBox speichert nicht die Sockets - sie hält auch einen Verweis auf diese Instanzen. Der ServerSocket verwaltet und hält diese hauptsächlich. Daher kannst du z.B. auch weiterhin die Connections[] des ServerSockets durchgehen um den Nickname zu zu ordnen. Andere Möglichkeit: Du baust dir ein Objekt - besser eine kleine Klasse - die nix weiter enthält als 2 Variablen im Public Bereich:
Delphi-Quellcode:
Und wenn du nun bei der ListBox einfach anstatt dem Socket folgendes hinzufügst:
TUserSocket = Class
Public Socket : TCustomWinSocket; NickName : String; End;
Delphi-Quellcode:
Somit haben wir es nun so, das wir nicht mehr direkt den Socket reinhängen sondern diese Instanz von TUserSocket die uns beide nötigen Informationen hält: Den Socket und den Nick. Nun fehlt noch die Zuordnung vom Nick:
Procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
Var lTemp : String; lUser : TUserSocket; Begin Memo1.Lines.Add(timetostr(now)+' Neuer User betritt den Chat !'); edit10.text := 'User eingeloggt: ' + IntToStr(ServerSocket1.Socket.ActiveConnections); lUser := TUserSocket.Create; lUser.Socket := Socket; lUser.NickName := ''; // noch unbekannt, sind ja im Connect... lTemp := Socket.RemoteHost + ' ' + Socket.RemoteAddress; ListBox1.Items.AddObject(lTemp, lUser); End;
Delphi-Quellcode:
Nun enthält die TUserSocket in der ListBox auch den Nickname, wenn der denn ankommt.
// Diese Funktion geht nur durch die ListBox durch und sucht den TUserSocket zu dem übergebenen Socket
Function TForm1.FindUserSocket(ASocket : TCustomWinSocket): TUserSocket; Var i : Integer; Begin Result := Nil; For i := 0 To ListBox1.Items.Count-1 Do If ( TUserSocket(ListBox1.Items.Objects[i]).Socket = ASocket ) Then Begin Result := TUserSocket(ListBox1.Items.Objects[i]); Break; End; End; procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var lUser : TUserSocket; lText : string; begin lText := Socket.ReceiveText; lUser := FindUserSocket( Socket ); If ( Assigned(lUser) ) Then Begin lText := xorstring(lText, ''); lUser.NickName := Copy(lText, 1, 6); ShowMessage(lUser.NickName); End; End; Dadurch, das in der ListBox nun eine Instanz von TUserObject hängt die wir selber instanziiert haben, müssen wir uns um die Freigabe kümmern und natürlich die anderen Routinen abhändern.
Delphi-Quellcode:
Zu den ClientSocket/ServerSocket als Chat mit Nicks, Channels, etc siehe für Ideen und Hinweise auch den (bisher noch unkommentierten) Code von mir an:
Procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
Var i : Integer; lUser : TUserSocket; Begin // Socket ist eindeutig, daher haben wir durch das Connect schon diesen Socket auch in der ListBox. // Also: ListBox1.Items.Objects[] durchgehen, schauen wo dieser übergebene Socket ist und dann den // Eintrag löschen. Fertig! Memo1.Lines.Add(timetostr(now)+' User verlässt den Chat !'); edit10.text := 'User eingeloggt: ' + IntToStr(ServerSocket1.Socket.ActiveConnections-1); // noch ist ActiveConnections nicht aktuell! lUser := FindUserSocket( Socket ); If ( Assigned(lUser) ) Then Begin For i := 0 To ListBox1.Items.Count-1 Do Begin If ( ListBox1.Items.Objects[i] = lUser ) Then Begin ListBox1.Items.Delete(i); Break; End; End; lUser.Free; End; End; Procedure TForm1.Button1Click(Sender: TObject); Var lUser : TUserSocket; Begin // wenn ein Eintrag ausgewählt ist... If ( ListBox1.ItemIndex > -1 ) Then Begin // dann den mit AddObject() hinzugefügten TUserSocket mal rausholen lUser := ListBox1.Items.Objects[ ListBox1.ItemIndex ] As TUserSocket; ShowMessage(lUser.NickName + ' wurde gekickt'); // ... und dann einfach den Socket schliessen lUser.Socket.Close; End; End; ![]() MfG Muetze1 |
Re: Server disconnectet Client
:gruebel:
Code:
bin ich blöd ? Das muss doch bei type rein, oder ?
TUserSocket = Class
da kommt fehlermeldung: Zitat:
|
Re: Server disconnectet Client
das was du da hast ist eine vorwärtsdeklaration... du musst die klasse auch noch irgendwo "richtig" deklarieren (die abschnitte/methoden/felder der klasse etc)
|
Re: Server disconnectet Client
Moin!
Zitat:
Natürlich heisst es so
Delphi-Quellcode:
:wall: :wall: :wall:
Type
TUserSocket = Class Public Socket : TCustomWinSocket; NickName : String; End; MfG Muetze1 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz