MultiClient Server Service (CPU Auslastung)

Danielku15

Erfahrenes Mitglied
Hi Leute.
Ich arbeite gerade an einem kleinen Projekt für einen Kollegen. Ich hab mal das Projekt ausführlich beschrieben und die einzelen Problempunkte zu behandeln. Denn während des Schreibens ist mir doch aufgefallen, dass man fast ein Tutorial dafür erstellen könnte, sobald alles gelöst ist. Zum Thema:

Es geht um folgendes:
Ein Windows Service hat im Hintergrund einen Server (TcpListener) laufen. Der Server soll beim Verbinden eines Clients folgendes abwickeln: Nach einer Willkommensmeldung soll man beim Client Benutzername und Passwort eingeben können. (Konsole). Hier wäre toll wenn man das PW maskieren könnte. Zur Accountbestätigung wäre toll wenn man irgendwie die Lokal vorhandenen User checken könnte ob dieser auf dem Server vorhanden sind und gültig sind. Nachdem sich der User eingeloggt hat soll er in eine Befehlsaufforderung kommen. Hier will ich eigene Befehle definieren welche Unterschiedliche Aktionen auslösen: exit --> Verbindung Trennen, ShowCpuTemp --> ShowCpuTemp() aufrufen. Sprich ein Art eigener Telnet mit eigenen Befehlen (keine Win Konsole).

Was weiß ich
Ich hab mir schon ca. 10 Tutorials und andere Howtos gelesen wie das Erstellen von Servern und Services funktioniert. Kleiner Auszug:

http://www.codeguru.com/Csharp/.NET/net_general/article.php/c4603
http://www.geocities.com/egon_rath/win32-services.html
http://msdn2.microsoft.com/en-us/library/bbx2eya8.aspx
http://www.codeguru.com/Csharp/.NET/net_general/article.php/c4603
http://www.csharphelp.com/archives3/archive486.html
http://www.developerfusion.co.uk/show/3574/

Was hab ich.
Ich hab den Service, den TCP Listener welcher auf den Port horcht und Sockets annimmt. Hier kommt das erste Problem der Server hängt in einer Endlosschleife um abhängig vom oListener.pending() Ergebnis einen Client anzunehmen und die eigene Konsole zu starten.
C#:
while(this._bServerRunning)
{
    Socket oClient = this._oListener.AcceptSocket();
    // Konsole in neuem Thread mit Socket starten
}

Nur diese Schleife (in neuem Thread gestartet) sorgt logischerweise für eine Endlosschleife solange der Server rennt. Demzufolge resultiert eine CPU Last von >50%. Aber bei jedem Beispiel im Internet hab ich das genau so, oder ähnlicher Form gefunden. Wie soll ich das umgehen? Den Thread nach jedem Schleifendurchgang in einen Sleep schicken? Oder gibts da andere Möglichkeiten? TcpChannels verwenden? Was ist optimal?


Kommunikation zwischen Server und Client.
Die Konsole welche den Socket zur Verfügung hat, kann ja schon mal mit dem Client kommunizieren. Nur wie optimiere ich nun die Transaktion zwischen Client und Server. Ich möchte sobald ich auf dem Server über meine Output Methode einen String sende, dass dieser auch sofort angezeigt wird. Und sobald ich auf dem Server eine Eingabe erwarte (mittels Socket lesen), soll in der Konsole sofort ein Console.ReadLine prompt erscheinen wo der User im Client tippen kann, und die Daten per Bestätigung senden. Nur wie Optimiere ich diesen Ablauf dass der Client unabhängig vom Serverablauf funktioniert. Denn den Client so auf den Server abzustimmen dass immer abwechselnd x Bytes gelesen und y Bytes gesendet werden, ist nicht sehr portabel. Gibts da irgendwelche ;öglichkeiten vom Client aus über den Socket zu lesen ob der Server noch Daten zu senden hat welche man annehmen muss? Oder er vielleicht gerade auf eine Eingabe wartet?

Authentifizierung:
Ist es möglich anhand Username und Passwort über C# zu prüfen ob diese Userdaten auf dem System angelegt sind und gültig sind. Ich hab bisher nur gefunden wie ich die Benutzernamen auslesen kann, aber nicht wie und ob ich diese validieren kann.

Befehle
Und sobald die Interaktion zwischen Server und Client funktioniert so wie vorhin beschrieben sollten die Befehle auch kein Problem mehr sein. String an den Server schicken, Befehl Parsen und Daten zurück senden.

Ich hoffe ihr wisst bescheid.

Gruß Daniel
 
Zuletzt bearbeitet:

TommyMo

Erfahrenes Mitglied
Hi Daniel!

Ich versuche derzeit auch mir einen kleinen Server zu basteln und habe mich im Vorfeld mit diesem Tutorial beschäftigt. Hier wird ein kleiner TimeServer erstellt, der ebenfalls mehrere Clients bedienen kann.

Der Entwickler verwendet ebenfalls einen TcpListener und verpackt diesen in einen sogenannten Main-Thread. In Zeile 5 startet er den Main-Thread und übergibt ihm die Methode Run, in der dann die Requests der einkommenden Clients abhandelt.

Code:
1:  // Listener initialisieren und starten
2:  listener = new TcpListener ( 4711 );
3:  listener.Start ();
4:  // Haupt-Server-Thread initialisieren und starten
5:  Thread th = new Thread ( new ThreadStart ( Run ) );
6:  th.Start ();

Für jeden neuen Client wird ein neuer Thread angelegt und in einer Liste gespeichert (Details siehe Tutorial). Dadurch wird die CPU Auslastung stark reduziert.

Hoffentlich habe ich deine Problemstellung richtig verstanden. Ich habe den Server aktuell laufen und 4 Clients registriert. Meine CPU Auslastung liegt zwischen 0 und 4%.

Gruß,
Tom