Autor Thema: Frage zu TcpServerUtils und Einbindung in ReadFn  (Gelesen 148 mal)

Offline DS_Starter

  • Developer
  • Hero Member
  • ****
  • Beiträge: 2794
Frage zu TcpServerUtils und Einbindung in ReadFn
« am: 16 September 2018, 07:47:30 »
Guten Morgen,

ich bin gerade dabei das erste mal TcpServerUtils einzusetzen um einen TCP-Server aufzubauen und brauche mal etwas Hilfe bei der Verwendung.
Ich habe in anderen Modulen, die TcpServerUtils einsetzen in der ReadFn immer ein ähnliches Konstrukt gefunden. Hier das Beispiel aus MQTT2_SERVER_Read:

  my ($hash, $reread) = @_;

  if($hash->{SERVERSOCKET}) {   # Accept and create a child
    my $nhash = TcpServer_Accept($hash, "Log2Syslog");
    return if(!$nhash);
    $nhash->{CD}->blocking(0);
    readingsSingleUpdate($hash, "nrclients",
                         ReadingsVal($hash->{NAME}, "nrclients", 0)+1, 1);
    return;
  }

  my $sname = $hash->{SNAME};
  my $cname = $hash->{NAME};
  my $c = $hash->{CD};
  ........

Meine zwei grundsätzliche Verständnisprobleme sind:

1. Wenn in der ReadFn immer in den  if($hash->{SERVERSOCKET})-Zweig abgebogen wird (mit einem return darin), wie werden dann jemals Daten durch den darunter liegenden Code gelesen, da ja $hash->{SERVERSOCKET} immer existiert solange der Server offen ist ?
2. TcpServer_Accept liefert ja eine Hashreferenz zurück ($nhash) die "{CD}" enthält. Im Code unter der If-Bedingung wird "my $c = $hash->{CD}" verwendet. Ich habe aber bisher nirgendwo eine Stelle gefunden wo aus $nhash->{CD} $hash->{CD} wird.

Ich habe es bis jetzt zwar hinbekommen Daten mit dem Server zu empfangen, aber nur wenn ich ein solches Konstrukt in der ReadFn verwende:

if($hash->{SERVERSOCKET}) {   # Accept and create a child
   my $nhash = TcpServer_Accept($hash, "Log2Syslog");
   return if(!$nhash);
   $nhash->{CD}->blocking(0);
   my $client = $nhash->{NAME};
   $hash->{TCPPADDR} = (split '_', $client)[-2];
   my $c = $nhash->{CD};
   my $ret = sysread($c, $data, 1024);  # returns undef on error, 0 at end of file and Integer, number of bytes read on success.
   .....         

D.h. es klappt wenn ich das Datenlesen innerhalb des if($hash->{SERVERSOCKET})-Zweiges mache unter Verwendung von  $nhash->{CD}.

Irgendetwas übersehe ich was mich daran hindert TcpServerUtils so einzusetzen wie es andere Module vormachen.
Für ein paar Erläuterungen wäre ich euch sehr dankbar.

LG und einen schönen Sonntag,
Heiko
ESXi 6.5 auf NUC6i5SYH mit FHEM auf Debian 9/64 Bit  (Stretch), DbLog/DbRep mit MariaDB auf Synology 415+
Maintainer: SSCam, DbLog/DbRep, Log2Syslog, Dashboard (interims)
aktive Mitarbeit:SMAEM, SMAInverter
Kaffeekasse: https://www.paypal.me/HMaaz

Offline CoolTux

  • Developer
  • Hero Member
  • ****
  • Beiträge: 15690
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #1 am: 16 September 2018, 08:01:24 »
    if( $hash->{SERVERSOCKET} ) {               # Accept and create a child
        TcpServer_Accept( $hash, $hash->{'NAME'} );
        return;
    }

    # Read 1024 byte of data
    my $buf;
    my $ret = sysread($hash->{CD}, $buf, 2048);


    # When there is an error in connection return
    if( !defined($ret ) or $ret <= 0 ) {
        CommandDelete( undef, $name );
        Log3 $name, 5, " ($name) - Connection closed for $name";
        return;
    }

    ...

Bei mir geht es so ohne Probleme. Das Lesen erfolgt also außerhalb der Bedingung. Ganz zum Schluss wird dann $buf an eine bearbeitende Funktion weiter gegeben.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.me/MOldenburg
Mein GitHub: https://github.com/LeonGaultier
kein Support für cfg Editierer

Offline DS_Starter

  • Developer
  • Hero Member
  • ****
  • Beiträge: 2794
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #2 am: 16 September 2018, 08:08:14 »
Morgen Leon,

Zitat
Bei mir geht es so ohne Probleme....

Ja, ich weiß  :) Habe auch im AMAD-Modul nachgeschaut.
Kann nur nicht erkennen _wie_ bzw. warum es so z.B. auch bei dir funktioniert. Das ist ja gerade mein Hirnknoten....
ESXi 6.5 auf NUC6i5SYH mit FHEM auf Debian 9/64 Bit  (Stretch), DbLog/DbRep mit MariaDB auf Synology 415+
Maintainer: SSCam, DbLog/DbRep, Log2Syslog, Dashboard (interims)
aktive Mitarbeit:SMAEM, SMAInverter
Kaffeekasse: https://www.paypal.me/HMaaz

Offline CoolTux

  • Developer
  • Hero Member
  • ****
  • Beiträge: 15690
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #3 am: 16 September 2018, 08:13:14 »
Guten Morgen Heiko,

Eventuell liegt es am Open. So tief stecke ich da auch nicht drin. Damals hat mir Andre geholfen, ist schon ne ganze Weile her.
Zeig mal bitte Deine Open.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.me/MOldenburg
Mein GitHub: https://github.com/LeonGaultier
kein Support für cfg Editierer

Offline DS_Starter

  • Developer
  • Hero Member
  • ****
  • Beiträge: 2794
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #4 am: 16 September 2018, 08:22:46 »
Open ist ganz unspektakulär.

      $lh = "global" if(!$lh);
      my $ret = TcpServer_Open($hash,$port,$lh);
      if($ret) {       
          $err = "Can't open Syslog TCP Collector at $port: $ret";
          Log3 ($hash, 1, "Log2Syslog $name - $err");
          readingsSingleUpdate ($hash, 'state', $err, 1);
          return;
      }
« Letzte Änderung: 16 September 2018, 19:10:17 von DS_Starter »
ESXi 6.5 auf NUC6i5SYH mit FHEM auf Debian 9/64 Bit  (Stretch), DbLog/DbRep mit MariaDB auf Synology 415+
Maintainer: SSCam, DbLog/DbRep, Log2Syslog, Dashboard (interims)
aktive Mitarbeit:SMAEM, SMAInverter
Kaffeekasse: https://www.paypal.me/HMaaz

Offline rudolfkoenig

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 18999
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #5 am: 16 September 2018, 08:23:50 »
Zitat
Wenn in der ReadFn immer in den  if($hash->{SERVERSOCKET})-Zweig abgebogen wird (mit einem return darin), wie werden dann jemals Daten durch den darunter liegenden Code gelesen, da ja $hash->{SERVERSOCKET} immer existiert solange der Server offen ist ?
Die einzige Aufgabe der Instanz mit SERVERSOCKET ist TcpServer_Accept durchzufuehren (und evtl. noch Statistiken). Durch den Accept wird eine weitere Instanz des gleichen Typs angelegt die eine Verbindung repraesentiert und im ReadFn die eigentliche Arbeit macht:
- ohne SERVERSOCKET dafuer mit CD/FD, PEER und PORT. CD/FD enthaelt den neuen Filedeskriptor.
- mit TEMPORARY (damit es nicht gespeichert wird)
- SNAME verweist auf die "richtige" Instanz, damit man die Attribute abfragen kann.

Zitat
Ich habe aber bisher nirgendwo eine Stelle gefunden wo aus $nhash->{CD} $hash->{CD} wird.
Passiert indirekt: TcpServer_Accept traegt den neuen Filedeskriptor in die globale %selectlist ein, damit wird ReadFn von fhem.pl/select mit dem temporaeren Instanzhash aufgerufen, wenn Daten genau bei dieser Verbindung anstehen.

Siehe auch "list TYPE=FHEMWEB", bzw. "man -s2 accept",
Informativ Informativ x 2 Liste anzeigen

Offline CoolTux

  • Developer
  • Hero Member
  • ****
  • Beiträge: 15690
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #6 am: 16 September 2018, 08:31:22 »
Guten Morgen Rudi,

Vielen Dank für die gute Erklärung. Dann muss Heiko seine Funktion also auf jeden Fall auch außerhalb der Bedingung weiter funktionieren.


Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.me/MOldenburg
Mein GitHub: https://github.com/LeonGaultier
kein Support für cfg Editierer

Offline DS_Starter

  • Developer
  • Hero Member
  • ****
  • Beiträge: 2794
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #7 am: 16 September 2018, 08:38:03 »
Morgen Rudi,

danke für die Erläuterung der Zusammenhänge. Wie Cooltux schon schrieb, müsste es ja auch wie bei euch auch funktionieren.
Ich versuche es jetzt mit den neuen Erkenntnissen nochmal.
ESXi 6.5 auf NUC6i5SYH mit FHEM auf Debian 9/64 Bit  (Stretch), DbLog/DbRep mit MariaDB auf Synology 415+
Maintainer: SSCam, DbLog/DbRep, Log2Syslog, Dashboard (interims)
aktive Mitarbeit:SMAEM, SMAInverter
Kaffeekasse: https://www.paypal.me/HMaaz

Offline CoolTux

  • Developer
  • Hero Member
  • ****
  • Beiträge: 15690
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #8 am: 16 September 2018, 09:41:31 »
Versuch es mal in einem minimalistischen Modul. Nur die TcpServer Geschichten einbauen. Habe ich auch gemacht, aber nur um ein Netzwerkgeräte zu emulieren bei der Entwicklung eines Modules.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.me/MOldenburg
Mein GitHub: https://github.com/LeonGaultier
kein Support für cfg Editierer

Offline DS_Starter

  • Developer
  • Hero Member
  • ****
  • Beiträge: 2794
Antw:Frage zu TcpServerUtils und Einbindung in ReadFn
« Antwort #9 am: 16 September 2018, 18:00:24 »
Wollte nur noch mal kurz Rückmeldung geben, dass der TCP-Server nun so läuft wie ich es erwartet habe. Dank der Info von Rudi bezüglich der Zusammenhänge konnte ich eine Reihe von Fehlern beseitigen die sich vor allem aus dem Switchen des Hash-Kontexts bei dieser Verwendung ergeben haben.
Jetzt gehts an die Feinheiten mit den vllt. nächsten Hürden  ;)

Vielen Dank euch !

LG,
Heiko
ESXi 6.5 auf NUC6i5SYH mit FHEM auf Debian 9/64 Bit  (Stretch), DbLog/DbRep mit MariaDB auf Synology 415+
Maintainer: SSCam, DbLog/DbRep, Log2Syslog, Dashboard (interims)
aktive Mitarbeit:SMAEM, SMAInverter
Kaffeekasse: https://www.paypal.me/HMaaz
Gefällt mir Gefällt mir x 1 Liste anzeigen

 

decade-submarginal