![]() |
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. |
Re: TClientSocket / TSeverSocket --- Gruppenchat
Hallo HugoHase, was passiert denn, wenn sich jemand abmeldet?
|
Re: TClientSocket / TSeverSocket --- Gruppenchat
Sicherlich schaut sich keiner 400 Zeilen Source durch, ohne jegliche Fehlerbeschreibung von Dir... :zwinker:
|
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 |
Re: TClientSocket / TSeverSocket --- Gruppenchat
Hi,
Delphi-Quellcode:
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.
procedure TFenster.ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket); begin end; Mfg Net7 |
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: |
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:
Ich hoffe das es im Groben und Ganzen alles erläutert. cv ist ein Record wo ich alle Daten der Verbindung abspeichere.
//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; Mfg Net7 |
Re: TClientSocket / TSeverSocket --- Gruppenchat
Zitat:
Sprich: Socket.Connections[] Elemente entsprechen genau den bei den Handlern übergebene Socket Instanzen. Somit also noch deutlich einfacher... 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. |
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 |
Re: TClientSocket / TSeverSocket --- Gruppenchat
Zitat:
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:
|
Re: TClientSocket / TSeverSocket --- Gruppenchat
So ich hab das noch mal über arbeitet .... ich hoffe mir kann jemand sagen was daran falsch ist weil jetzt immer noch nen fehler kommt
Delphi-Quellcode:
procedure TFenster.ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket); var CO, i : integer; name, Liste : String; begin CO:=0; while Member[CO].hdl <> Socket.Handle do inc(CO); name:=Member[CO].name; for i:=CO to length(Member)-2 do Member[i]:=Member[i+1]; SetLength(Member,length(Member)-1); for i:= 0 to length(Member)-1 do //nur die verkleinern die gr als gelöschte con if (Member[i].CO >= 0) and (Member[i].CO > CO) then Member[i].CO:= Member[i].CO-1; for i:=CO to length(Member)-1 do ServerSocket.Socket.Connections[Member[i].CO].SendText('CO'+IntToStr(Member[i].CO)); ListBoxKontakte.Clear; Liste:=''; for i:=0 to length(Member)-1 do begin Liste:=Liste+Member[i].name+'|'; ListBoxKontakte.Items.Add(Member[i].name); end; sleep(500); for i:=0 to length(Member)-1 do ServerSocket.Socket.Connections[i].SendText('LI'+Liste); sleep(1000); 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; |
Re: TClientSocket / TSeverSocket --- Gruppenchat
Hi,
das mit den ganzen Schleifen kann ich nicht wirklich nachvollziehen, da wird man ja wirr im Kopf :pale: Du solltest jeder Schleife wenn sie denn wirklich nötig ist , eine eigene Schleifenvariblen zuweisen. Da durch die Optimierungen des Compilers die Schleifen nicht so durchlaufen werden wie du es willst, schmeiß mal den den Debugger an und überzeuge dich. Baue deinen Code um. Mfg Net7 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:43 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