Multiprocessing oder Timeout bei socket->recv

93 views
Skip to first unread message

Topos

unread,
Jul 30, 2012, 3:20:07 PM7/30/12
to fhem-de...@googlegroups.com
Hallo FHEM Gemeinde,
 
Rudi hat mich darauf hingewiesen, dass man bei "langsamen" LAN-Verbindungen die Kommunikation mit dem Webserver in einen Child Prozeß bzw. Hintergrund-Task einbauen soll. Jetzt habe ich schon fleißig gesucht aber nichts dazu gefunden. Die Anleitung unter dem Development Guidelines auf der FHEM -Wiki verstehe ich nur teilweise.
 
Letztendlich ist es so, dass in dem Modul die Sequenz
 
my $socket = new IO::Socket::INET (
                 PeerAddr => $host,  
                 PeerPort => $port,
                Proto => 'tcp'
);
$socket->recv($result, $length);
 
immer vor dem Erreichen der $length abbricht und socket->recv deshalb solange neu aufgerufen werden muss, bis alle Bytes eingelesen wurden. Das selbe Modul funktioniert unter PHP problemlos, deshalb vermute ich, dass es in perl (FritzBox 7390) einen Timeout gibt.
 
Auf meine etwas weniger ausführliche Anfrage per Mail hatte Rudi geantwortet:
 
ich sehe das Problem noch nicht, versuche zu raten: Damit die Daten
vollstaendig gelesen werden, hast Du eine lokale Schleife gebaut, der den
restlichen fhem behindert.

Die Loesung: Man liest den Rest nicht in einer lokalen Schleife der ReadFn,
stattdessen triggert ReadFn einfach nichts solange die Daten unvollstaendig
sind, und sammelt die bisher aufgelaufenen Daten in dem PARTIAL Hash Eintrag.
Erst wenn der komplett ist (laenge/crc/etc), werden die Daten analysiert und
via Trigger etc weitergereicht.

Mein KM271 laeuft auch nur mit 2400 Baud, liefert also seine Daten nach und
nach, stoert aber niemanden.

Du darfst/sollst sowas gerne in der Gruppe fragen, damit ich es nicht jedem
separat erzaehlen muss.
 
 
Irgendwie verstehe ich aber nicht, wie ich diese Schleife bauen soll und warum socket->recv immer abbricht. Könnt Ihr mir vielleicht eine "Vorbild"-Modul empfehlen?
 
Gruß
 
Topos 

Rudolf Koenig

unread,
Jul 31, 2012, 2:44:56 AM7/31/12
to fhem-de...@googlegroups.com
> Irgendwie verstehe ich aber nicht, wie ich diese Schleife bauen soll

- Im XXX_Define DevIo_OpenDev() aufrufen. Dieser kann auch ein client socket
oeffnen, aber das wesentliche ist $conn->fileno() ins $hash->{FD}, bzw. $hash
in den globalen %selectlist einzutragen (wird von DevIo_OpenDev erledigt).
Damit wird per globalen select auf die Verbindung aufgepasst, und wenn was zu
lesen gibt, dann wird XXX_ReadFn aufgerufen.

- XXX_ReadFn liest die Daten normalerweise per DevIo_SimpleRead(). XXX_ReadFn
muss danach feststellen, ob die Nachricht komplett ist. Wenn ja, dann werden
diese verarbeitet, wenn nicht, dann werden die Daten ueblicherweise im
$hash->{PARTIAL} bis zum naechste Aufruf zwischengespeichert.

- Falls die andere Seite nicht erreichbar ist, dann wird der Status von
DevIo_SimpleRead auf DISCONNECTED gesetzt, und solange im Abstand von 5
Sekunden XXX_ReadyFn aufgerufen (indem man $hash in %readyfnlist eintraegt),
bis dieser die Verbindung wieder (mit DevIo_OpenDev) oeffnen kann.



> warum socket->recv immer abbricht.

Weil es nicht blockieren will, und die Daten noch nicht komplett vorliegen.


> K�nnt Ihr mir vielleicht eine "Vorbild"-Modul empfehlen?

contrib/00_TAHR.pm
Reply all
Reply to author
Forward
0 new messages