Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!
25.10.2007, 23:09 (Dieser Beitrag wurde zuletzt bearbeitet: 25.10.2007 23:30 von eg.)
ich habe Probleme mit TCP/IP-Server-Listener-Multiple Clients u.s.w. Kann mir bitte jemand sagen wie ich vorgehen muss. Folgendes:
Ich will einen TCP Dispatcher progammieren. Seine Aufgabe ist neue Clients anzumelden(in eine Tabelle eintragen) und ankommende Pakete nach Themen zu sortieren(filtern) und zu den angemeldeten Clients abzuschicken.
Ein Client öffnet eine Verbindung zum Dispatcher-Server auf, meldet sich bei ihm an und sendet/empfängt Pakete zum/vom Dispatcher.
Habe schon mehrere Server/Client und Multiple Connections Beispiele angeschaut, habe aber einige Verständnisprobleme bezüglich Listener. Es gibt zwei VIs, die fast dasselbe machen:
TCP Listen.vi und TCP Create Listener.vi
Diese habe unterschiedliche Refnum-Ausgänge, schliessen sich aber gegenseitig aus, warum? Gibt es kompetente Leute im LVF, die mir das erklären könnten? Sorry, bin in Panik.
So weit ich das verstanden habe ist TCP/IP eine Eins zu Eins Verbundung.
Heißt das jedem Client ist ein Server zugeordnet? Wie funktionieren dann die Web Server? Ich habe immer gedacht, daß ein Web Server jede Verbindung annimmt, jede Anfrage ausführt und dann die Antwort zum betreffenden Client abschickt. Ist es falsch?
Aem,
1:1 ist etwas unguenstig ausgedrueckt, sag lieber verbindungsorientiertes Protokoll, was durchaus mehrere Clients auf einem Server bedienen kann.
Der Kernpunkt ist jedoch, dass jeder Client (jede TCPIP Refnum) explizit angesprochen werden muss und es kein Broadcast wie bei UDP gibt.
Multiple Client - Single Server Architecture sieht so aus, dass der Server im Grunde genommen zwei Schleifen besitzt. Eine Schleife hat ausschließlich die Aufgabe, mit dem TCP Listener neue Verbindungen anzunehmen und die Refnum von dem entsprechenden Client in die "Lebenslinie" der zweiten Schleife einzubauen.
Zusaetzlich zur Erkennung empfiehlt es sich, in der Listener Schleife auch eine ID zu speichern, die der Client beim 1. Anmelden am Server direkt abfeuert. D.h. die Lebenslinie ist ein Cluster mit X Elementen, wobei ein Element des Clusters mit Sicherheit die TCP Refnum ist.
Danke für die Antwort, es hat mich nicht viel weiter gebracht. In den Links geht es mehr um das Protokoll, mit dem Protokoll habe ich aber keine besondere Probleme. Mir geht es mehr darum alle Verbindungen anzunehmen, das mache ich in einer getrennten Schleife, die RNs in einem Array zu speichern, so weit bin ich auch, aber was nicht klappt ist: VON ALLEN VERBINDUNGEN (quasi)gleichzeitig die Daten auszulesen.
Ich habe mir gestern folgende Überlegungen gemacht:
ich werde wie bis jetzt in einer Schleife Verbindungen annehmen und diese im Array abspeichern, wenn ich irgendwas ZUM CLIENT abschicken will, wähle ich die richtige Rn aus und schicke die Daten ab.
Wichtig ist, wie sollen die Clients die Daten zum Dispatcher abschicken, besser gesagt wie soll der Dispatcher die Daten von den Clients auslesen?
So habe ich mir gedacht, daß ich PRO CLIENT dynamisch eine Schleife starte (sogenannter Dienst). Diese Schleife wird die Daten von dem Client auslesen und in eine Queue schreiben, diese Queue wird vom Dispatcher ständig ausgelesen und die empfangenen Daten werden entsprechend ausgewertet.
Wäre das die richtige Vorgehensweise?
Danke, eg
P.S. für das Protokoll habe ich mir zwei Wrapper gemacht: TCP_WriteWrapper und TCP_ReadWrapper. Diese Warpper bekommen am Eingang Nutzdaten, fügen die Paketgröße vornedran und Schicken das Paket ab oder beim Lesen halt umgekehrt.
Hmmm, bevor du die Refs im Array abspeicherst, koenntest doch die Ref direkt an ein Reentrant SubVI welches per VI Server dyn aufgerufen wird, uebergeben.
Der Client muss dann ein ein-eindeutige ID bekommen, dadurch kannst auf einen Shared Memory (bspws Queues) die Daten an einem zentralen Punkt sammeln und entsprechend der ID zuteilen, auswerten oder wie auch immer...
26.10.2007, 09:54 (Dieser Beitrag wurde zuletzt bearbeitet: 26.10.2007 10:04 von eg.)
Hier zwei Loops: die obere ist Dispatcher, liest eine Queue aus und macht irgendwas abhängig vom empfangenen Befehl. Führt ausserdem eine Tabelle mit Clients. Die untere überwacht einen Port und nimmt alle Verbindungen von den Clients. Sobald ein Client eine Verbindung aufmacht, startet diese Loop ein reentrantes VI (Dienst, von dem ich gesprochen habe, siehe nächstes Bild)
Das ist der Dienst, er macht nichts anderes als die Pakete vom Client zu empfangen und in die Dispatcher Queue zu schreiben. Dieser Dienst ist reentrant und wird für jeden Client gestartet.
Auf diesem Bild ist ein Beispiel, wie so ein TCP CLient aussehen kann.
ich hab's zu spät gelesen, aber ich mach das auch mit reentranten "client VI". Für jeden Client, der sich zum Server verbundet wird eine neue Instanz aufgemacht, die mit der "connection ID" gefüttert wird und diesen Client bedient. Ich hab auf die Art und Weise einen Server geschrieben, der momentan mit bis zu 20 Clients läuft.
' schrieb:ich hab's zu spät gelesen, aber ich mach das auch mit reentranten "client VI". Für jeden Client, der sich zum Server verbundet wird eine neue Instanz aufgemacht, die mit der "connection ID" gefüttert wird und diesen Client bedient. Ich hab auf die Art und Weise einen Server geschrieben, der momentan mit bis zu 20 Clients läuft.
Kannst du mir ein Beispiel deines Pub/Subs geben? Ich persönlich finde dieses Pattern sehr interessant und werde wahrscheinlich alle meine mittlere und große Projekte damit machen. Insbesondere weil alles zentral abläuft alles sehr übersichtlich ist und deshalb gut debugfähig. Leider sind die meisten Programmierer nicht interessiert daran oder verwenden das "unbewusst". Das Muster öffnet sehr viele Möglichkeiten ist aber mit einem Overhead verbunden, was aber mit allen Vorteilen überwogen wird. Ich werde wahrscheinlich ein Tutorial auf meiner Webseite aufmachen, damit mehr Leute darüber erfahren.
Ich empfehle es allen auszuprobieren. Wenn sich jemand fragt was ich davon habe, dann meine Antwort dazu:
ich will Feedback, Anerkennung und vielleich euere Initiative, vielleicht wird daraus eine von allen verwendbare Bibliothek.
In Zukunft will ich mehr Kommunikationsmethen implementieren. Queues hatte ich schon in meiner allerersten Version, jetzt TCP/IP, dann will ich noch Notifier und User Events implementieren, damit wir vieles erschlagen sein.
Probiert es aus und sagt mir bitte womit ihr Schwierigkeiten habt. Euere Vorschläge zur Implementierung und Verbesserung sind auch willkommen.
eg
P.S. Sorry, ich verstehe nicht warum so wenig Leute daran interessiert sind.
' schrieb:Kannst du mir ein Beispiel deines Pub/Subs geben? Ich persönlich finde dieses Pattern sehr interessant und werde wahrscheinlich alle meine mittlere und große Projekte damit machen. Insbesondere weil alles zentral abläuft alles sehr übersichtlich ist und deshalb gut debugfähig.
was sind Pub/Subs? <blond guck>
damit ich dir die VIs zeigen kann müsste ich die aus den Projekten rausziehen, aber da ist eine NDA drauf => keine gute Idee und "veröffentlichbar" nachprogrammieren .... hmmm ... keeene zeit, keene lust
aber ich versuchs mal zu erklären:
in meinem Server VI gibts mehr oder weniger 2 parallele Schleifen.
Die eine wartet ständig auf eine eingehende Verbindung, nimmt diese an und startet dynamisch - wenn was reingekommen ist - ein reentrantes VI, das nenn ich mal "Client VI". Die zweite Schleife im Server ist eine queued state machine, die quasi "die Arbeit verrichtet".
Jedes Client VI erzeugt bei seinem Start eine eigene Queue und hat eine "mini Statemachine". Damit das Client VI möglichst klein ist und wenig Ressourcen benötigt, besteht das VI mehr oder weniger nur aus ein paar Queue und TCP funktionen.
Der "Trick" dabei ist, die "Arbeit" vom Server verrichten zu lassen, und das Senden und Empfangen über TCP durch die "Client VIs". Das ist wichtig, damit sich verschiedene Clients nicht gegenseitig blocken können, z.B. wenn der Versand von Daten bei einer Anfrage an den Server mal was länger dauert oder so.
Wenn das Client VI eine Anfrage vom Client empfängt, dann wird diese geparst und in die Queue der StateMachine des MainVIs geschoben. Neben dem Befehl und den Daten bekommt das MainVI noch die Queue Referenz von der Q des jeweiligen Client VIs, wo nach dem Abarbeiten die "Antwort des Servers" reingeschoben wird. Das Client VI kümmert sich dann wieder darum, dass die Daten verschickt werden.
Ein paar Erfahrungen, die ich dabei gesammelt habe:
Es ist sinnvoll im Client VI eine Art Timeout zu implementieren, z.B. max. Lebensdauer des VIs - wenn keine Datenübertragung stattfindet - von 10 minuten => das hält den Speicher frei
Ich hab eine "ClientID" eingeführt, das war im Prinzip einfach eine Old Style Global, die bei jedem Start eines Clients VIs hochgezählt wurde. Die ID hab ich bei der Übergabe der Anfrage an die MainQ mitgeschickt, das ist ganz praktisch beim Debuggen, dann weiß man gleich, von welchem Client das stammt
die TCP/IP kommunikation hab ich nach dem Prinzip: vorweg 4 Byte, danach die Daten aufgebaut, wie im Example findert. Das ist die einfachste Methode dem Server mitzuteilen, wieviel Daten man denn nun tatsächlich schickt.
Für die Server-Anfragen (="Befehle") hab ich einen Cluster aufgebaut, aus einem Enum, und einem String, in den ich die Daten flatte ...