Genau das ist mein Problem.
Ich Benutze ein Client Socket, um eine Verbindung zu einem Lantronix UDS2100 aufzubauen. Dies ist ein RS232/Ethernet Wandler. Die Empfangenen Daten können über den TCP-Port 10001 Empfangen werden.
Dies funktioniert an sich sehr gut, aber wenn ich die TCP-Verbindung únterbreche oder das Gerät neu startet, so merkt der Client Socket das nicht. Es gibt kein Error oder ähnliches. Es kommen nur keine Daten mehr an. Ich muss dann den Socket des Client Socket trennen und erneut Verbinden. Dann funktioniert das wieder.
Das ist mein Problem, was eigendlich nicht sein dürfte…
Wenn der Device-Server noch andere Ports im Netz anbietet (z.b. Port 80 für Webinterface) könntest Du über eine PHP-Portabfrage regelmäßig prüfen ob das Teil noch Online ist. So nach dem Strickmuster:
$IP = IP-Adresse
$Port = Port Nummer
@$s = fsockopen($IP, $Port, $errno, $errstr, 1);
if (!$s) {
echo "Gerät nicht erreichbar";
}
else {
echo "Gerät Online.";
}
fclose($s);
Das Problem ist nicht, wie ich den Portzustand ermitteln kann => Port im Fehlerzustand (Rotes Ausrufezeichen).
In meinem Fall ist der Client Socket NICHT im Fehlerzustand, funktioniert aber nicht. Dies Passiert, wenn das Entgerät kurzzeitig keine Verbindung hatte (LAN-Kabel unterbrochen) oder neu gestartet wurde. Die TCP-Session ist definitiv nicht mehr vorhanden. Der Client Socket Port geht aber nicht in den Fehlerzustand oder baut die Verbindung erneut auf. Erst durch manuelles trennen und neuverbinden funktioniert die Client Socket Instanz wieder.
Es hilft daher nicht den Status des Client Sockets abzufragen: der ist immer „OK“.
Bei meinen Client-Socket funktioniert das. Wenn ich den Endgeräten den Saft klaue oder die Verbindung kappe geht der Socket auf Fehler, so wie es sein soll. Erst Dunkel grau, dann Rot.
Du musst auf dem Socket alle paar Minuten/Sekunden von IP-Symcon etwas raussenden. Oder auf der anderen Seite immer etwas senden, damit der Socket offen bleibt, oder IP-Symcon erkennt, dass der Socket von Windows „aufgeräumt“ wurde.
Alle Module in IP-Symcon senden ein KeepAlive alle 60 Sekunden. Somit wird auch spätestens nach 60 Sekunden ein „kaputte“ oder „tote“ Verbindung erkannt und entsprechend neu aufgebaut. Außerdem verhindert das KeepAlive, dass Windows die Verbindung aufräumt
So, ich habe nun das nochmal genau analysiert. Im Standardfall empfängt mein Client Socket nur Daten von einem Netzwerkgerät. IPsymcon sendet selber nichts. In dieser Konstellation ist es definitiv so, dass der Zustand der Socketverbindung vom Client Socket nicht überprüft wird. Fällt also das Netzwerkgerät aus oder die Netzwerkverbindung reißt ab, so passiert nichts. Es kommen nur keine Daten mehr an. Der Port zeigt KEINEN Fehler, auch nicht 2 Tage später…
Sende ich auf den Socket per Script was und dieser hat vorher die Verbindung verloren, so wird der Port sofort auf Error gesetzt und die Verbindung erneut aufgebaut. Dies ist die gewünschte Reaktion bei Verbindungsabbrüchen.
Daher Frage ich nun: Ist das so gewollt, dass nur beim senden der Port auf Fehler reagiert oder ist das ein Bug?
Ich habe genau das gleiche Problem mit meinem USR RS485/LAN-Adapter. Wurde der Adapter (kurz) neu gestartet, werden keine Daten mehr von IPS empfangen, obwohl der Client Socket keinen Fehler anzeigt.
Einen Ping an den USR kann ich erfolgreich aus IPS senden.
Erst, wenn ich etwas über den Client Socket senden möchte (CSCK_SendText()), zeigt der Client Socket einen Fehler an (rotes Ausrufezeichen) und fängt an die Verbindung erfolgreich neu aufzubauen.
Alternativ kann ich auch den Client Socket kurz schließen und wieder öffnen.
Gibt es denn eine bessere Lösung als jede Minute eine Nachricht über den Client Socket zu senden?
Kann ich vielleicht ein Ereignis erstellen, dass mich informiert, wenn eine Variable schon länger als eine Minute nicht mehr aktualisiert wurde?
Nall chan hatte da glaub ein Modul oder Skript, wo man solche Überwachungen machen konnte.
Alternativ kannst du sowas aber auch einfach selbst umsetzen mit IPS_GetVariable und dem Timestamp in „VariableUpdated“
In dein Skript/Modul dann einfach sowas wie „if (time() - VariableUpdates > 60)“ und dann den Socket z.B. schließen (IPS_SetProperty), IPS_ApplyChanges, öffnen (IPS_SetProperty), IPS_ApplyChanges.