Konzeptionsfrage zu Daten, GUI und Server

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Konzeptionsfrage zu Daten, GUI und Server

    Hi.

    Ich schlage mich bereits eine ganze Weile mit einem Projekt herum bei welchem ich ziemlich auf mich alleine gestellt bin.

    Kurz umrandet:

    Es gibt eine GUI über welche viele Einstellungen vorgenommen werden.
    Diese Einstellungen sind relational verknüpft, daher liegen die Daten in einem typ. Dataset und diese sind an diverse Controls gebunden und werden als XML gespeichert.
    Die GUI Struktur und das Databinding steht.
    Der zweite Teil umfasst einen Proxyserver welcher verschiedene Clients hält.
    Der Server nimmt Verbindungen von Clients entgegen und leitet Daten entsprechend der Einstellungen weiter.

    Nun zu meiner Frage.
    Wie würdet ihr mir empfehlen, diese Daten an die Server Klasse bzw. Client Klasse zu übergeben?
    Mein erster Ansatz war, das komplette DataSet an den Server zu übergeben und jeder Client erhält seine entsprechende Datarow mit seinen Einstellungen.
    Dieser Ansatz gefällt mir allerdings nicht.

    Was ich erreichen möchte ist:
    Die Einstellungen sollen zur Laufzeit des Servers geändert werden können und dann auch greifen
    Beispielhaft dafür ist zB eine maximale Idletime. Soll heissen, nach einer gewissen Zeit von inaktivität sollen ein Client automatisch getrennt werden.
    Diese Einstellung soll jedoch auch zur Laufzeit ohne Neustart des Servers übernommen werden können.
    Zudem soll es möglich sein, Änderungen über diverse (bereits bestehende) Dialoge zu ändern, ohne dass diese sofort greifen.
    Erst beim Apply sollen diese tatsächlich an den Server und die Clients weitergegeben werden.

    Ich habe hierbei einfach ein generelles Konzeptionsproblem.
    Ich möchte möglichst alle Bereiche getrennt behandeln.
    Also als einzelne Projekte einer Projektmappe.
    Ein Hinweis auf MVC und so weiter sind sicher nett gemeint, allerdings habe ich halt eben mit der Umsetzung meine Probleme.
    Bzw. halt generell mit der Konzeption dieses Projekts.
    Wenn ich nicht deutlich genug beschrieben habe, was ich möchte und wo mein Problem liegt, werde ich dies gerne noch ausführlicher machen^^

    Danke für Antworten

    Gruss Mono
    Das ist meine Signatur und sie wird wunderbar sein!
    Sowas ähnliches versuche/mache ich auch für mein 2.5D Game - soll ja einen Multiplayer haben^^

    Ich habe SpielDaten und ServerClientDatenaustausch auch voneinander getrennt. Die Verbindung zwischen beidem kann später ganz einfach hergestellt werden, denn der GameTCPClient/Server feuert ein Event sobald er ein Update empfangen hat.

    Übertragen werden die Daten in kleinen Datensätzen (z.B. Datensatz für Positionsangabe, Spielerstatistik, Punktestand + genauere Aufschlüsselung, etc) übertragen - das ist mehr Arbeit, reduziert aber die zu übertragende Datenmenge. Das ist bei mir wichtig, die Position soll schließlich ca. 50 mal pro Sekunde übertragen werden, würde ich ständig die Namen aller Spieler etc mitsenden, hätte ich ein Problem xD
    Ich denke mal, dass du mit kleineren Wartezeiten (sind später sicher weniger als 1 Sekunde, soviel kann ein Dataset, dass evtl noch komprimiert übertragen wird nicht braucehn) leben kannst, würde ich immer das komplette DataSet übertragen und der Server analysiert (liest z.B. Punkte die an ihn gerichtet sind aus und setzt sie um) und leitet ggf weiter. Wann gesendet wird ist ja sache der Clients, ich sehe da kein Problem, dass Einstellungen erst nach einem klick auf den OK-Button übertragen werden oder eben sobald sich etwas ändert.

    Ein eigens "Protokol" würde ich aber dennoch aufbauen. So könntest du z.B. dem Server beibringen, dass er die Einstellungen der einzelnen Clients intern speichert - ein Client der sich connected kann dann eine anfrage senden und seine Einstellungen abrufen. Ein zurücksetzen wäre so auch sehr leicht möglich. Ist eben schon praktisch wenn Server und Client richtig miteinander sprechen können^^ Auf die weise lässt sich auch die TimeOut-Funktion sehr leicht machen: Alle paar Sekunden sendet der Client eine "Hallo-hier-bin-ich"-Nachricht an den Server - dieser schaut ob die Nachricht regelmäßig ankommt oder über einen längeren Zeitraum nicht. Jenachdem wie das aussieht kann er handeln (Verbindung trennen, andere Clients kontaktieren, etc).

    Nur aus Neugierde: Was sind das überhaupt für Einstellungen? Was soll das Programm mal machen?^^

    lg
    Die Daten die zwischen Server und Client ausgetauscht werden sind nicht manipulierbar und nahezu irrelevant.
    Der Server fungiert nur als Proxy und leitet Daten von Clients an ein Hostsystem weiter.

    Die Einstellungen sind die Daten, die der Server benötigt um zu wissen, welche Clients wohin "verbunden" werden sollen.
    Ein kleines Beispiel:
    Am Server wird ein Netz eingetragen mit NetzIp und Subnetmaske.
    Für diese Clients wird eine bestimmte ZielIp hinterlegt.
    Diese Daten sind alle in einem Dataset.

    Der Server selber nimmt also Clients entgegen und anhand seiner Einstellungen baut er eine Verbindung zum Ziel auf.
    Die Frage die ich habe bezieht sich auf das: Wer verwaltet dies am besten?
    Ich könnte zB dem Server das DataSet übergeben, und dieser weiss damit, wohin sich ein Client verbinden soll.
    Dabei kommt allerdings das Problem zu Tage, dass zum einen der Server komplett asynchron arbeitet, man aber über die GUI das Dataset zur Laufzeit auch ändern können muss.
    Es könnte aber auch so sein, dass der Server nur Events rausfeuert, wenn sich ein Client verbindet oder trennt, und die Einstellungen quasi von einem Controller anhand des Datasets vorgenommen werden, welcher nur Nachrichten vom Server empfängt, und die Logik nicht im Server steckt.

    So auch bei der Leerlaufzeit. Leerlaufzeit bedeutet, ein Client sendet keine Daten.
    Das heisst, jedesmal wenn der Client Daten sendet, beginnt ein Timer zu laufen, welcher die Leerlaufzeit prüft. Ist die maximale Leerlaufzeit erreicht, wird der Client getrennt.
    Auch hier könnte das zB direkt in der Client Klasse selber geschehen, in der Serverklasse oder eben außerhalb.
    Also in der Klasse, welche den Server "bedient".

    Ich hoffe es ist halbwegs verständlich.
    Das ist meine Signatur und sie wird wunderbar sein!
    Dein Server macht scheinbar 2 unterschiedliche Dinge:

    Zum einen nimmt er KonfigurationsEinstellungen entgegen - vermutlich von einem Client, der über besondere Rechte verfügt (Admin)

    Zum andern verbindet er Clients entsprechend diesen Konfigurationen.
    Das Konfigurations-Dataset wird also ühaupt nicht mit den normalen Clients kommuniziert, sondern nur mit dem Admin-Account.
    Jo, das wird nicht so häufig sein, dass man das da nicht komplett übertragen könnte.

    Was ich nicht verstehe, warum den Clients vom Server her Einstellungen gesendet werden - sollen die daraufhin ihre Oberfläche ändern, oder was steckt dahinter?

    Jedenfalls beruhen Client-Kommunikation und AdminClient-Kommunikation auf 2 ganz verschiedenen Kommunikations-Protokollen.
    Die Einstellungen werden am Server benötigt und von diesen abhängig werden Clients unterschiedlich behandelt.
    Ich werde mir nochmal überlegen, wie ich das ganze klarer darstelle.
    Das ist meine Signatur und sie wird wunderbar sein!
    So

    Ich versuche es nochmal, da ich grad etwas Zeit auf Arbeit habe ^^

    Ich habe eine Klasse Server. Diese Klasse Server startet einen TCP Listener, welcher per BeginAcceptClients Clients annehmen kann.
    Verbindet sich ein Client, dann wird eine Klasse Proxy-Client instanziert.
    Diese Klasse beinhaltet dann den TCP-Client, der sich am Listener connected hat und einen 2. TCP-Client, welcher eine Verbindung zu einem Host System aufbaut.
    Zu welchem System und über welche IP, dass wird über die Einstellungen entschieden.
    Die Proxy Client Klasse macht dann folgendes:
    Alle eingehenden Daten vom 1. TCP-Client werden an den 2. TCP-Client weitergeleitet.

    Die Einstellungen sehen (vereinfacht) in etwa wie folgt aus:
    Ein Datensatz:
    DataTable Routing:
    IP|SubNetMaske|LogLevel|max IdleTime|ZielIp|ZielPort|max. Anzahl Clients| .. (u.a.)

    Verbindet sich also ein Client mit der IP 10.10.10.1 wird geprüft, in welchem Netz befindet sich diese IP.
    Abhängig davon wird eine Verbindung zu einem Zielsystem aufgebaut (und zwar zur eingetragenen ZielIp/ZielPort)
    Der Sinn dahinter ist zweitrangig.

    Fakt ist, dass der 2. Client eine Verbindung abhängig von den Daten im DataTable aufbaut.

    Ich habe also eine GUI um den Proxy Server zu bedienen (Start/Stop) und einige Dialoge, um die Einstellungen ändern zu können.
    Die Clients sind nicht von mir programmiert. Diese verwenden ein spezielles Protokoll, welches hierfür unerheblich ist.
    Der Server fungiert nur als Vermittler und soll quasi statisch routen und noch ein wenig mehr.

    Die Frage ist, wo würdet ihr die Logik einbauen und wie würdet ihr das DataSet verwenden.
    In die Klasse Server, in die Klasse Client oder eine weitere Klasse zwischen Server und GUI?


    Ich hoffe es ist jetzt nicht noch unklarer was ich möchte ^^
    Das ist meine Signatur und sie wird wunderbar sein!
    Zunächstmal würde ich die Logik in den Server stopfen - erst später auslagern, wenn sich herausstellt, essis sehr kompliziert (ca. >300Zeilen)
    Aber scheint mir ja nicht weiter kompliziert:
    Ein Client connected sich, zunächstmal am TcpListener. Dann wird da dieser TcpClientProxi erstellt und konfiguriert, anhand der DataTable. Meinetwegen auch die DataRow mit in den TcpClientProxi hineingeben - dann kann man ihn von aussen noch um-konfigurieren.

    Datasetse lege ich immer global an, weil wennich schoma sowas hab, dann kommen da auch alle Daten der Anwendung rein.
    Also die Forms, mit denen du das Dataset editierst, haben im Designer ein lokales Dataset.
    Dieses musste zur Laufzeit als erstes umstöpseln auf das globale Dataset.
    Weil vmtl. willste das konfig-Form ja man iwann schließen - das Dataset soll aber weiter in Betrieb sein.
    Ok.
    Also so wie ich es schon hatte.
    Und wie würdest du das Dataset threadsafe "machen"?
    Und wie bringt man am besten eine Transaktionsfunktionalität ins Dataset?
    Das heisst, dass über Dialoge am Dataset, welches via Databinding gebunden, rumdoktort, die Änderungen aber erst bei "Übernehmen" auch ins Dataset geschrieben werden?
    Und dementsprechend der Server dann erst die neuen Einstellungen zur Verfügung hat?

    Auf jedenfall schonmal Danke ^^
    Das ist meine Signatur und sie wird wunderbar sein!
    na, ok, bei Transaktionslogik darf das Gui nicht auf den original-Daten rumorgeln.
    also muß beim Start des Dialogs eine Dataset-Kopie gezogen werden, die nur bei Ok zurück-kopiert wird.

    Dassis eiglich ganz nett, weil dann brauchst du evtl. nichtmal die Designer-Datasetse umzustöpseln, sondern kannst sie genau als diese Kopie benutzen.

    Dataset hat übrigens auch Merge-Funktionalität - ich weiß aber nicht, wie da die Logik ist.
    Ich täte ja hoffen, dass man Datasetse in derselben Weise mergen kann, wie auch das Update an eine Datenbank ein Merge-Vorgang ist: Es werden nur Änderungen angefasst, der Rest bleibt unberührt.

    Ansonsten würdich halt sone Merge-Funktionalität programmieren, weil das wäre schon fabelhaft: DataTables raisen ja Events, wenn eine Row geändert wird, und darauf könnteman differenziert reagieren, und genau die Client-Proxies anweisen, sich zu rekonfigurieren, dies auch angeht.
    So.

    Ich habe jetzt ein globales Dataset.
    Meiner Dialogform übergebe ich dieses Dataset.
    In der Dialogform habe ich die Controls via Designer an ein (lokales) Dataset gebunden (also mit BindingSource).
    Setze ich dieses nach InitializeComponents via globDataSet.Copy, aktualisieren sich die Controls nicht.

    Setze ich das lokale Dataset vor InitializeComponents und ändere ich dort:

    VB.NET-Quellcode

    1. Me.DsProxyServerConfig = New ProxyProjekt.dsProxyServerConfig

    auf

    VB.NET-Quellcode

    1. If me.DsProxyServerConfig Is Nothing Then Me.DsProxyServerConfig = New ProxyProjekt.dsProxyServerConfig


    Dann funktioniert es (und der Designer funktioniert auch noch)
    Allerdings muss es doch auch eine Möglichkeit geben, die BindingSource über das geänderte DataSet zu informieren und die Controls zu aktualisieren..
    Habe bisher noch nicht rausgefunden wie das geht.
    Ich kann höchstens die Datasource der Controls auf Nothing setzen und dann wieder an die BindingSource binden.
    Wie mache ich das am besten ?

    Gruss Mono
    Das ist meine Signatur und sie wird wunderbar sein!
    ich wandle in solchen Fällen die Binderei ein bischen:
    Das Form bekommt eine MainBindingSource, die ans lokale Dataset angeschlossen ist. Alle weiteren BindingSources werden an die MainBindingSource angeschlossen - keine ans lokale Dataset.
    Dann kann ich zur Laufzeit die Datasource der Mainbindingsource durchs globale Dataset ersetzen und feddich.
    Das kann das Form sogar im Form_Load selbst erledigen, denn das globale Dataset ist ja global.