Hallo zusammen,
ich versuche gerade einen Fehler in einem entstehenden Modul zu finden.
Konkret geht es darum beim Restart von FHEM einen zuvor geöffneten IP-Socket zu schließen. Er wird geöffnet mit:
my $socket = IO::Socket::Multicast->new(
Proto => 'udp',
LocalPort => '9522',
$socket->mcast_add('239.12.255.254');
$hash->{TCPDev}= $socket;
$hash->{FD} = $socket->fileno();
......
Es ist jeweils eine Routine als {UndefFn} und als {ShutdownFn} definiert und initialisiert. Beide Routinen sind gleich:
#####################################
sub
SMAEM_Shutdown($$)
{
my ($hash, $arg) = @_;
my $name= $hash->{NAME};
my $socket= $hash->{TCPDev};
Log3 $hash, 3, "$name: Closing multicast socket...";
$socket->mcast_drop('239.12.255.254');
$socket->close;
return undef;
}
#####################################
sub
SMAEM_Undef($$)
{
my ($hash, $arg) = @_;
my $name= $hash->{NAME};
my $socket= $hash->{TCPDev};
Log3 $hash, 3, "$name: Closing multicast socket...";
$socket->mcast_drop('239.12.255.254');
$socket->close;
return undef;
}
Alles klappt prima wenn "rereadcfg" ausgeführt wird, d.h. die sub SMAEM_Undef.
Nur bei einem FHEM-Shutdown klappt das Schließen des Sockets nicht (in seltenden Fällen klappt es auch hier). Demzufolge finden sich im Log nach dem FHEM-Start entsprechende Socketfehler die darauf hinweisen dass der Socket beim Shutdown nicht geschlossen wurde :
Can't bind : IO::Socket::Multicast: Die Adresse wird bereits verwendet
Wird nach dem Restart wieder "rereadcfg" ausgeführt, funktioniert das Schließen und Eröffnen des Sockets.
Hat jemand eine Idee woran das Problem liegen könnte ?
viele Grüße
Heiko
Das liegt höchstwarscheinlich an der Tatsache, dass beim Shutdown zuerst die UndefFn und danach die ShutdownFn ausgeführt wird. Bei einem rereadcfg wird nur die UndefFn ausgeführt.
Wenn also ein Shutdown ausgeführt wird, wird 2 mal versucht den Socket zu schließen. In der UndefFn funktioniert das auch, in der ShutdownFn ist der Socket ja bereits zu.
Da es meiner Meinung nach keinen Grund gibt eine ShutdownFn explizit damit zu belegen, solltest du dir die ShutdownFn klemmen und nur die UndefFn verwenden.
Gruß
Markus
Hi Markus,
danke für deine schnelle Antwort ... ich habs gleich mal mehrfach ausprobiert.
Gleiches Bild , shutdown mit Socketproblem , reread klappt prima... hmm
Gruß
Heiko
Ich habe mit Multicast noch keine Erfahrung, aber bei den normalen Sockets muss man ReuseAddr => 1 setzen, sonst blockiert der naechste Server-Bind-Aufruf (falls es zeitnah geschieht) mit dem gemeldeten Fehler. Vielleicht braucht IO::Socket::Multicast auch sowas. Btw. wozu braucht man heutzutage multicast?
Hallo Rudi,
danke für die Idee ... schaue ich mal in die Richtung ...
ZitatBtw. wozu braucht man heutzutage multicast?
Die SMA-PV-Geräte wie Wechselrichter, SMA Energy Meter verwenden Multicast. Wir basteln (d.h. Volker bastelt und ich unterstütze etwas beim Test) hier https://forum.fhem.de/index.php?topic=51569.0 (https://forum.fhem.de/index.php?topic=51569.0) an einer FHEM integrierten Lösung um ohne zusatzliche Softwarekomponenten wie SBFspot o.ä. auszukommen.
Grüße
Heiko
zusätzlich zu ReuseAddr ist es vermutlich auch sinnvoll ReusePort zu setzen. sonst kann nur ein prozess auf diesem port lauschen. leider ist das nicht auf allen plattformen verfügbar. das kann man so abfangen:ReusePort=>defined(&ReusePort)?1:0)
wenn es mit beiden flags immer noch nicht geht schau mal ins fakeRoko (und plex) modul. da verwende ich ebenfalls IO::Socket::Multicast.
@rudi: es gibt noch diverse protokolle die multicast verwenden u.a. ssdp um upnp geräte (alle möglichen audio und video geräte, die hue bridge, ...) zu finden, plex gdm, und noch einiges mehr.
wenn man auf dem netzwerk lauscht kommt da eine ganze menge vorbei.
gruss
andre
Hi Andre,
super ... danke ! Da schaue ich mal rein bzw. teste das ...
Gruß
Heiko