Frage zu IO::Socket und IO::Select

Begonnen von esskaa, 11 Dezember 2016, 01:36:33

Vorheriges Thema - Nächstes Thema

esskaa

Hallo zusammen,

leider kann ich keinen Thread im Developement Teil aufmachen, darum dann hier.
Ich bin gerade dabei ein Modul zu schreiben. Mit Perl bin ich aber nicht so fit.

Die Aufgabenstellung ist ganz einfach: TCP Kommunikation. Die Lösung ziemlich tricky, zumindest für mich.
Das Problem:
$socket->recv($data,4);
Bleibt einfach hängen. Ich habe es mit BlockingCall() versucht, da bekomme ich lustiger weise nie ein recv zustande. Warum das so ist verstehe ich auch nicht, nachvollziehbar ist das für mich nicht. Ich habe aber festgestellt das BlockingCall() unter Windows mit Strawberry Perl erst gar nicht funktioniert, es bricht den Child nie ab. Unter Linux funktioniert es wie erwartet, mit der gleichen Einschränkung das recv funktioniert generell nicht und die Routine läuft immer in einen Timeout.

BlockingCall() widerstrebt mir ein wenig da es sich um 10 Bytes handelt die ich senden und empfangen muss, da ist nicht lange Blocking angesagt. Unter Python habe ich das gleiche Problem schon gelöst, dort half mir die SELECT Funktion. Unter Perl sieht das dann bei mir so aus:

@ready = IO::Select->new($socket)->can_read(0.5);
if (@ready) {
    $socket->recv($data,4);
}


Dieser Code sollte nach maximal einer halben Sekunde abbrechen, wenn er nichts empfängt.
Jetzt kommt das kuriose:
Bevor ich das Modul für FHEM gemacht habe, habe ich einen Standalone PoC gemacht. den Code vom PoC habe ich 1:1 in das FHEM Modul übernommen.
Lasse ich den PoC in einer Schleife laufen, dann funktioniert das uneingeschränkt. Ich habe ich das nun über Nacht getestet und über 10.000 mal durch laufen lassen. Ca. 3% der recvs enden mit einem Timeout. An keiner Stelle bleibt das Programm hängen.

In FHEM als Modul sieht das nun etwas anders aus, 95% der Timeouts werden richtig und ohne Probleme abgehandelt. In 5% der Fälle bleibt einfach das ganze FHEM hängen. Gibt es da einen Trick? Gibt es eine bessere Lösung?

LG,
Sascha

P.S.: Falls das hier das falsche Forum ist, bitte verschieben wenn möglich.

viegener

Ich habe jetzt nicht direkt eine Lösung zu Deinem spezifischen Problem hier, würde aber raten nochmal einen Schritt zurückzugehen. Es gibt eine ganz Menge Module in FHEM, die I/O (auch über Netzwerk machen). Die meisten davon verwenden zentrale Mechanismen, um die Daten aus filehandles/sockets zu lesen. Dafür gitb es gute Gründe, da FHEM selbst nicht in sich multithreaded gebaut ist und wenn Dein Modul aktiv auf Daten wartet steht der ganze Server still.

Deshalb mein Ratschlag, nimm doch ein existierendes Modul, mit Netzwerkkommunikation am besten, als Vorlage und bringe Deine Funktionalität darin unter. Selbst wenn das Modul nur für Dich sein sollte, macht es Sinn die existierenden Mechanismen in FHEM zu verwenden für die eigenen Input/Output-Funktionen.

Es gibt inzwischen im fhemwiki auch einiges an Developer Intro.

Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

esskaa

Danke viegener für Deine Antwort. Auch wenn mich das nur sehr bedingt weiter bringt, ist es nett das Du Dir die Zeit genommen hast. Ich werde dann einfach mal weiter tüfteln bis ich das passende für mich gefunden habe.