[de] Benutzung der Klasse ServerSession

Topics: Technical Support
Nov 23, 2011 at 11:02 AM

Hallo,

mein anderes Problem wurde erfolgreich behoben, nun habe ich mich damit befasst, wie ich von meiner Server Console Informationen über angemeldete Clients und Informationen von Clients über andere Clients bekomme.

Wie ich gelesen habe ist der Sessionmanager falsch, da der nur im Server werkelt.

Nach etwas recherche kam ich auf die Klasse ServerSession, die wohl auch Informationen über den Server an die Clients überträgt. Hier in dem Forum habe ich dann folgenden Eintrag gefunden.

            // Identität des Aufrufers ermitteln
            IIdentity callerIdentity = ServerSession.CurrentSession.Identity;

            // Benutzernamen des Aufrufers ausgeben
            Console.WriteLine(callerIdentity.Name);

Dieses gehört wohl auf den Server, wegen der Konsolenausgabe aber bei mir füllen sich die Werte "Name" z.B. nicht. Okay dachte ich mir, ich muss beim Verbindung aufbauen natürlich die Werte erst hinzufügen.

Also habe ich versucht Clientseitig eine ServerSession Klasse zu instanziieren, welches aber nicht von erfolg gektrönt war, da folgende Fehlermeldung erschien.

                        Fehler 1 Für den Typ "Zyan.Communication.ServerSession" sind keine Konstruktoren definiert.

Wie beschreibe ich dann also z.B. den Identity.Name? Dies im Client zu tun sollte ja korrekt sein, oder?

 

Mit freundlichen Grüßen

Tarzipan

Coordinator
Nov 24, 2011 at 11:39 PM

Hallo Tarzipan,

die Klasse ServerSession steht nur serverseitig zur Verfügung. Mit ServerSession.CurrentSession kannst Du die aktuelle Sitzung abrufen. Die Sitzung des Aufrufers wird von Zyan automatisch an den Arbeitsthread gehängt, welcher die aktuelle Clientanfrage verarbeitet. Die ServerSession wird nicht an den Client übertragen. Vor allem wird die Sitzung nicht anderen Clients preisgegeben. Client A sollte niemals den Sitzungsschlüssel (SessionID) von Client B wissen.

Wenn ich Dich richtig verstanden habe, möchtest Du Informationen über aktuell angemeldete Clients (Anzahl, Benutzernamen und IP-Adressen) allen Clients als Dienst zur Verfügung stellen. Jeder Client soll also abfragen können, was auf dem Server gerade los ist und wer sich dort tummelt. Um das zu erreichen musst Du eine Serverkomponente bereitstellen, welche die Informationen auf Anfrage beschafft und deren Abfrage ermöglicht. Diese Serverkomponente kann auch gleichzeitig als SessionManager verwendet werden.

So könnte das aussehen:

public class ExtendedSessionManager : InProcSessionManager, IClientInfoService
{
    public ExtendedSessionManager() : base()
    {

    }
        
    public List<Shared.ClientSession> GetActiveClientSessions()
    {
        return (from s in AllSessions
                select new ClientSession() 
                { 
                    UserName = s.Identity.Name, 
                    TimeStamp = s.Timestamp 
                }).ToList();
    }
} 

public
interface IClientInfoService { List<ClientSession> GetActiveClientSessions(); }

[Serializable] public class ClientSession { public string UserName { get; set; } public DateTime TimeStamp { get; set; } }  

Damit Zyan mit Benutzeridentitäten und dem ExtendedSessionManager arbeitet, muss des Code fürs Hosting entsprechend angepasst werden:

ExtendedSessionManager sessionManager = new ExtendedSessionManager();
var protocol = new TcpBinaryServerProtocolSetup(8080)
{                
    UseWindowsSecurity=true                
};
            
using (var host = new ZyanComponentHost("ClientInfo", protocol, sessionManager))
{
    host.RegisterComponent<IClientInfoService, ExtendedSessionManager>(sessionManager);

    Console.WriteLine("Server läuft");
    Console.ReadLine();
}

Auch die Clientseite benötigt zusätzliche Informationen:

var protocol = new TcpBinaryClientProtocolSetup()
{
    UseWindowsSecurity = true
};
                        
using (var connection = new ZyanConnection("tcp://server:8080/demo", protocol))
{
    IClientInfoService proxy = connection.CreateProxy<IClientInfoService>();

    var clientSessions = proxy.GetActiveClientSessions();
                
    foreach (var clientSession in clientSessions)
    {
        Console.WriteLine(string.Format("Zeitstempel:{0}, Benutzer:{1}", clientSession.TimeStamp, clientSession.UserName));
    }
    Console.ReadLine();
}

IP-Adressen kann derzeit nur das TcpDuplexProtocolSetup auflösen. Bei anderen ProtocolSetups ist die Eigenschaft ClientAdress von ServerSession immer leer.
Das liegt daran, dass Remoting grundsätzlich abstrakt und nicht an ein bestimmtes Protokoll gebunden ist. Beim IpcChannel kann es z.B. gar keine IP-Adressen geben.

Hinzu kommt, dass der Standard-TCP-Kanal, welcher standardmäßig verwendet wird, sich in Sachen IP-Adresse in Mono anders verhält als in Microsoft.NET.

Wenn es für Dein Projekt wichtig ist, die IP-Adressen der anderen Clients abrufen zu können, musst Du das TcpDuplexClientProtocolSetup sowie das TcpDuplexServerProtocolSetup verwenden.
Das hat noch weitere Vorteile. So kann des Duplex-Modus z.B. Events und Callbacks durch Client-Firewalls hindurch empfangen, ohne dass man dafür Ports öffnen muss.
Allerdings unterstützt TcpDuplexServerProtocolSetup keine Integrierte Windows-Sicherheit. Stattdessen kann man aber den BasicWindowsAuthProvider verwenden. Dieser verlangt aber
Benutzername und Kennwort als Credentials von jedem Client. Natürlich kannst Du Dir auch ganz leicht einen eigenen Authentifizierungs-Provider schreiben, der alles genau so macht,
wie Du es haben willst.

Gruß

Rainbird