Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Serversocket wie Clients Unterscheiden ? (https://www.delphipraxis.net/69310-serversocket-wie-clients-unterscheiden.html)

Real_Thunder 13. Mai 2006 09:04


Serversocket wie Clients Unterscheiden ?
 
Moin, ich bin es schon wiuieder.. nach einer nacht durchgrübeln.... komme ich einfach nicht weiter :wall: :wall: :wall: :wall:

diesmal geht es um die TServerSocket Compnente.. und bitte nun keine posts von wegen dann minn doch INDY

also.. alles was ich wissen mächste ist wie ich verschiedene Clients auseinanderhalten kann also kleines bespiel..

client 1 hat daten die fpr client 3 bestimmt sind... wie sage ich dem serve nun das er die daten zu client 3 packen soll

eine ganz 'Böse' lösung wenn man es berhaupt so nennen könnte währe mit einer schleife einen befehl zum identifizieren geben , und wenn der identifizierung stimmt dann soll er das packet dort hin senden.. dauert aber lange, und frißt recourcen.....
also gbt es nicht eine möglichkeit der verbindug gleich beim commenten einen wert zuzuweisen der sich fr diese verbindung nicht mehr ändert ?

also wie quasi serversocket1.socket.connections[x] ..... oder so ähnlich...

ich hoffe ihr könnt mir auch dabei weiterhelfen

Vieln dan im vorraus

gsh 13. Mai 2006 09:28

Re: Serversocket wie Clients Unterscheiden ?
 
Du könntest dir ein Array abspeichern mit den ganzen Sockets.

D.h. wenn jetzt ein neuer Client dazukommt dann merkst du dir des Socket und halt andere Infos (z.b. Client1) in einem Record. In dieses Record speicherst du in dem Array.

Ich hoff des hilft dir weiter. Funktionieren tuts auf alle fälle hab ich auch schon gemacht und bei mir hats gefunkt

Net7 13. Mai 2006 09:36

Re: Serversocket wie Clients Unterscheiden ?
 
Also in meinem Projekt hatte ich es über die Handlenummer der Verbindungen gelöst, die bei jedem angedockten Clienten anders ist.
Schau dir mal die Sache mit den Handles näher an und du bist der Lösung schon recht nahe ;)

Über die Handlenummern kannst du dann auch die Connections ermitteln, ist übrigens viel sicherer als die Sockets zu zählen und durchzunummerieren. Eine Verbindung kann ja auch mal abreißen wenn sich ein Client aufhängt oder so..

Mfg Net7

Real_Thunder 13. Mai 2006 09:49

Re: Serversocket wie Clients Unterscheiden ?
 
Habe es schon eimal mit de rHanldnummer versucht... also ich weise dann quasi nur beim onclient connect die handlingnummer den jeweiligen client zu

aber wie kann ich ruckschlüsse von der handlignummer auf die verbindung ..

ch habe da eine leichte idee, werde mich gleich mal ransetzten.. ich hatte die handlingnumemr auch schnal gehabt.. nun weiß ich allerdings nicht ehr wie ich dazu gekommen bin...
aber jetzt wo du es sagst, ich kan mir die handlingnummer beim on connect oder ersten on'read holen, sobald der client seinen ident sendet, und spter wenn ich diesen client brauche ein schleife machen

werde es erstmal versuchen... melde mich dann wiedeer

Grüße Real_Thunder

Net7 13. Mai 2006 10:11

Re: Serversocket wie Clients Unterscheiden ?
 
Also ich habs in etwa so gemacht.

Bischen Bastelcode: Auszug!!

Und Teile meines Projects...

Delphi-Quellcode:

const
      MaxAnzCon=100;


Type
     TAInt=array[0..MaxAnzCon] of Integer;


 Type
     TClientenverwaltung=record
     Con           : TAInt; // Socketnummer
     HNr           : TAInt; // dazugehörige Handlenummer
     isOnline      :array [0..MaxAnzCon] of boolean; // ist er auch noch online
     end;


.....
CV:TClientenverwaltung;


// CV ( Clientverwaltung) Array mit Anfangswerten beschreiben    
procedure TNet7Server.Init;
(* -------------------------------------------------------------------------- *)
var
i: Integer;
begin
     
    // Serverliste mit Wert -1 füllen
    for i := 0  to MaxAnzCon do
      begin
          cv.Con[i] := -1;
          cv.HNr[i] := -1;
          cv.isOnline[i] := false;
     end;

end;

//Clienten in Liste aufnehem bei Event ClientonConnect   funktionsfähig
procedure TNet7Server.ClientOnList;
(* -------------------------------------------------------------------------- *)
var
LZaehler: Integer;
begin
       LZaehler := 0;
            //zähle solange hoch bis du einen freien Paltz (-1) in der Liste findes
            while cv.HNr[LZaehler] > -1 do
              begin
                    inc(LZaehler);
               end;


                 cv.HNr[LZaehler] := socket.Connections[socket.ActiveConnections-1].Handle;
                 cv.isOnline[LZaehler] := true;
                 cv.Con[LZaehler] := socket.ActiveConnections-1;

               
               
end;
Ich hoffe der Code hilft dir weiter, die Überwachung ob der Client Online ist bzw seine Löschung geb ich dir noch nicht... "Sebst ist der Mann" aber wenn du da irgendwie hängenbleibst geb ich dir gerne wieder Tipps ;)

Über den Aufruf des Records also cv[x].bla hast du die Socketnummer, die Handlenummer und umgekehrt...


mfg Net7

// Edit: Einen Stolperstein möchte ich ich dir noch ersparen.

Bedenke!!!!!
Sobald ein Client offline geht rutscht die Socketnummer einen Wert tiefer und die gespeicherte Handlenummer im Record stimmt mit der Socketnummer im Record nicht mehr überein.

Muetze1 13. Mai 2006 15:46

Re: Serversocket wie Clients Unterscheiden ?
 
Warum nur immer so umständlich?

Folgende Punkte dazu als Ideen/Hinweise:

1. In den Ereignisen wird immer ein Socket vom Typ TCustomWinSocket übergeben. Diesen findet man immer in der Connection[] Eigenschaft vom Server wieder. Jederzeit, bei jedem Ereignis. Selbst beim OnDisconnect wird dieser erst nach Abarbeitung des Ereignis-Callbacks entfernt.
2. Die Instanz des TCustomWinSocket, welcher übergeben wird und in der o.g. Eigenschaft vorhanden ist, ist eindeutig über seine Lebzeit. Mit anderen Worten: Wenn ihr die Instanzenadresse als "Handle" nutzt ("Handle" := Integer(Socket)), dann ist diese eindeutig vom OnClientConnect Ereignis bis zum OnClientDisconnect Ereignis. (Wobei hier ein direktes vermerken der Socket Instanz einfacher ist, da man so einfach den Socket bei der Hand hat, wenn man die Informationen von anderer Seite aus seinem Datengrund herausholt.)
3. Wenn ihr zusätzliche Informationen zu den Sockets verwalten wollt, dann definiert euch einen Record oder eine Klasse und legt sie darin ab. Die eindeutig Zuordnung schafft ihr durch vermerken der Record Adresse bzw. der Instanz der Klasse in der Data Eigenschaft des TCustomWinSockets. So legt den Record bzw. die Klasse im OnClientConnect an und weist ihn zu - beim OnClientDisconnect gebt ihn wieder frei. In allen zwischenzeitlichen Ereignissen bekommt ihr den Socket mit an den Kopf geworfen, also einfach die Data Eigenschaft nutzen und ihr wisst, um welchen Client es geht.

Um zur ersten Frage von mir zurück zu kommen: Wozu eine Socket/Handlenummer verwalten, wenn die Socket-Instanz eindeutig ist, verwaltet wird und zusätzliche Informationen (Data Eigenschaft) aufnehmen kann.

Net7 13. Mai 2006 20:39

Re: Serversocket wie Clients Unterscheiden ?
 
hmm... und was ist, wenn es kein OnDisconnect-Ereignis gibt, weil der Client abgestürzt ist ???

Mfg Net7

Muetze1 13. Mai 2006 21:44

Re: Serversocket wie Clients Unterscheiden ?
 
Zitat:

Zitat von Net7
hmm... und was ist, wenn es kein OnDisconnect-Ereignis gibt, weil der Client abgestürzt ist ???

Dann ist die Socket Instanz trotzdem gültig. Diese wird erst nach einem OnDisconnect gelöscht, somit kein Problem. Wenn du dir selber eine Art Ping in dein Protokoll implementierst, dann kannst du diesen Absturz selber mitbekommen und selber den Socket mit Close schliessen (Socket.Close -> löst auch wieder ein OnDisconnect aus). Auch wenn beim senden ein Fehler kommt oder sonstiges, alles kein Problem mit den o.g. Methoden.

Im OnError empfehle ich grundsätzlich den angegebenen Socket mit Socket.Close zu schliessen, da man nach einem Fehler von dem Socket bei den TServerSocket/TClientSocket nix mehr erwarten kann.

Real_Thunder 15. Mai 2006 09:46

Re: Serversocket wie Clients Unterscheiden ?
 
So ich habe es mit
Delphi-Quellcode:
Socket: TCustomSocket

connect_id:= integer(socket);
geamcht.

Es geht Wunderbar.
Das Ergebnis speichere ich zusammen mit einer Identnummer des users.
Das Array sieht dann so aus:
Delphi-Quellcode:
Element 1: connect_id user_id
Element 1: connect_id user_id
Element 1: connect_id user_id

aber die kann ich nun direct rückschlüsse ziehen aus der connect id

bis jetzt habe ich es so gemacht
Delphi-Quellcode:
for y:=0 to serversocket1.Socket.ActiveConnections-1 do begin
  if inttostr(integer(serversocket1.Socket.Connections[y]))= find_client[0] then begin
    serversocket1.socket.Connections[y].SendText('Testtext'');
  end;
end;
Und es funktioniert.. (Sieht aber nciht besonders Schön aus)


Gibt es eine möglichkeit das integer(Socket) wieder rückgängig zu machen ? also quasi ein Socket(integer)

Net7 15. Mai 2006 10:24

Re: Serversocket wie Clients Unterscheiden ?
 
Zitat:

...aber die kann ich nun direct rückschlüsse ziehen aus der connect id
Was meinst du damit genau, was für Rückschlüsse möchtest du denn haben ?

Mfg Net7

Real_Thunder 15. Mai 2006 10:37

Re: Serversocket wie Clients Unterscheiden ?
 
Ich möchte anhand des
Delphi-Quellcode:
Integer(Socket)
eine Verbindung aufbauen können, ohne vorher mit einer schleife die werte zu vergleichen.

also ich meie quasi dieses:
Delphi-Quellcode:
for y:=0 to serversocket1.Socket.ActiveConnections-1 do begin
  if inttostr(integer(serversocket1.Socket.Connections[y]))= find_client[0] then begin
    serversocket1.socket.Connections[y].SendText('Testtext'');
  end;
end;
durch nur einen befehl ersetzten

Hmmm.. So has ich angand der Socket id , die Passene Verbindugg raussuchen kann

Net7 16. Mai 2006 10:08

Re: Serversocket wie Clients Unterscheiden ?
 
Schreib dir doch eine Funktion.

Real_Thunder 17. Mai 2006 01:02

Re: Serversocket wie Clients Unterscheiden ?
 
Jups werde ich machen, so spare ich mir wneigstens ein wenig source code...

Muetze1 17. Mai 2006 07:15

Re: Serversocket wie Clients Unterscheiden ?
 
Wozu? Gelesen was ich geschrieben hatte? Man kann mit dem Integer sich eine eindeutige ID zusammenbauen - oder am besten einfach das ganze als TCustomWinSocket lassen, da die Instanz wie gesagt schon eindeutig ist. Somit ersetze den Integer in deiner Clientverwaltung durch TCustomWinSocket und leg direkt ohne Type-Cast den Socket darin ab.

Der Integer beinhaltet die Instanzenadresse, somit ist er eindeutig - aber warum den Typ noch auf Integer umschreiben wenn er als Socket doch viel nützlicher ist?

Ansonsten nach deinem bisherigen Aufbau würdes du dir die Schleife ersparen können, da du den richtigen Socket in deiner Struktur vorliegen hast. Folgender Code ersetzt deine komplette Schleife:

Delphi-Quellcode:
TCustomWinSocket(find_client[0]).SendText('Wozu eine Funktion?');
/EDIT: PS: Was ich gerade sehe: warum legst du den Socket bzw. die Socket ID als String ab??? Warum nur? Somit ändert sich der Code noch weiter:

Delphi-Quellcode:
TCustomWinSocket(StrToInt(find_client[0])).SendText('Viel zu kompliziert gemacht (die Clientverwaltung).');
Einen Integer zu vergleichen wäre deutlich schneller, komfortabler und fehlerfester.

Net7 17. Mai 2006 08:32

Re: Serversocket wie Clients Unterscheiden ?
 
Ähm.. also nun frag ich mich ernsthaft was an meiner Lösung ( weiter oben )so umsändlich sein soll.


Delphi-Quellcode:

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
        TNet7Server.ClientOnList;
end;
ich muss meine Procedure nur dort reinbasteln und schon hab ich was ich brauche die Handlenummer und die dazugehörige die Verbindung. Alles steht im Record.
Ist doch viel Eleganter als sich mit den TCustomWinSocket noch auseinanderzusetzen.

Mfg Net7

Real_Thunder 17. Mai 2006 08:42

Re: Serversocket wie Clients Unterscheiden ?
 
Nichts gegen deine Lösung, die scheint ja auch recht kompfortabel zu sein.

Doch ich bin im allgemeinen noch nicht so bewandert in Delphi, benutze es erst seit 2 Wochen

Mit der Records und der Zuordnung zu der Connection verstehe ich die Logik nicht ganz.
Es mag Funktionieren, aber wenn ich nicht verstehe Wie es Funktioniert dann benutze ich es lieber nicht.
Sobald ich mich mit dem Kram auseinandergesetzt habe, und es verstehe wede ich mir die anderen vorschläge noch mal anschauen.

MfG Real Thunder

Muetze1 17. Mai 2006 13:41

Re: Serversocket wie Clients Unterscheiden ?
 
Zitat:

Zitat von Net7
Ähm.. also nun frag ich mich ernsthaft was an meiner Lösung ( weiter oben )so umsändlich sein soll.

Ich bezog mich auf Real_Thunder, aber ich kann auch gerne zu deiner Lösung nochmal noch ein paar Aussagen treffen:

1. Durch MaxAnzCon ist deine Logik/Verwaltung auf 100 Clients begrenzt und nicht dynamisch erweiterbar.
2. Warum, besser, wofür merkst du dir das Sockethandle? Wozu brauchst du dieses in der Clientverwaltung da du doch alles mit den Instanzen der TCustomWinSockets erledigst (bzw. deren Methoden)
3. Was nützt dir ein "Online" Flag, wenn es doch einfach festzustellen geht: Wenn ein Socket vorhanden ist, ist er online, ist er nicht mehr vorhanden, dann ist er offline. Egal ob nun im Connections[] Array des Server Sockets oder sonstwo vermerkt.
4. Deine Eigenschaft "Con" ist nicht eindeutig, sie kann mehrfach vergeben werden bzw. wird mehrfach vergeben. Wozu brauchst du diese dann? Wozu dient diese Eigenschaft?

Vor allem frage ich mich, was dir diese Verwaltung bringt? Im Normallfall ist das Problem doch die Zuordnung von zusätzlichen Daten den Sockets und nicht zu wissen welche Sockets zZ am Server hängen. Letzteres kann man einfach und sofort durch Iteration der Connections[] Eigenschaft ermitteln.

Wenn ich zusätzliche Informationen verwalten will (ist der Client authentifiziert, welcher Client (z.B. Name) ist das, etc), dann würde ich eine Klasse erstellen welche in einer TObjectList verwaltet wird. Diese Klasse bekommt eine Eigenschaft oder öffentliche Variable vom Typ TCustomWinSocket und lebt genauso lange wie der Socket zu der sie gehört. Alle zusätzlichen Informationen die ich zu den Clients verwalten will bzw. speichern will, werden darin vermerkt. Beim Connect wird die Instanz der Klasse erstellt, der Objectlist zugefügt und der Eigenschaft Data des Sockets. Die Instanz bekommt auch den Socket zugewiesen auf die Eigenschaft.

Folgende zwei Beispielfälle:
- Ein Client disconnected: ok, ich hole mir die Instanz aus der Data Eigenschaft des Sockets, entferne diese aus der Objektliste und gebe sie frei (wenn nicht schon von der TObjectList abhängig von OwnsObject schon getan).

- Ich will eine Nachricht an alle authentifizierten Clients schicken: Ich laufe über alle Elemente der Objektliste und für jedes Element welches authentifiziert ist, sende ich eine Nachricht direkt durch Aufruf der SendText() Methode der vermerkten Socket Instanz - ohne vorher das Connections[] Array für jedes Element abzuklappern.

Ich für meinen Teil würde das dann noch weiter spinnen und keine TObjectList nutzen sondern eine Ableitung von dieser implementieren, welche dadurch besondere Methoden bekommen kann. So z.B. eine Methode der Liste für SendToAll(), etc.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:31 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