Hallo
Ich habe folgende Ausgangslage:
1) Ich habe ein Embedded Linux Gerät mit einem Webserver am laufen
(Server).
2) Zusätzlich habe ich ein weiteres Gerät (Client) welches über Ethernet
meistens direkt am Server angeschlossen ist, kann aber auch über
Switches etc. weiter entfernt sein.
Auf dem Client läuft ebenfalls ein Embedded Linux. Der Client hat nur
einen Touchscreen, keine weiteren Bedienmöglichkeiten. Darauf ist ein
Browser installiert (voraussichtlich Chromium) welcher im Kiosk-Mode
läuft, hat also keinerlei zusätzliche Bedienung.
Wenn der Client keine Verbindung zum Server aufbauen kann, soll dies dem
Benutzer optisch ansprechend mittels einer Webseite gezeigt werden. Auf
keinen Fall darf jemals eine Fehlerseite z.B. ERR_NAME_NOT_RESOLVED des
Browsers angezeigt werden. Denn ohne F5 Taste zum aktualisieren kommt
man von einer solchen Seite nie wieder weg. Stattdessen soll eine andere
lokal auf dem Client gespeicherte Webseite angezeigt werde z.B. mittels
eines weiteren lokalen Mini-Webservers auf dem Client.
Meine Idee ist es nun, auf dem Client einen DNS-Dienst so zu
konfigurieren, dass dieser die Anfragen des Browsers an den Server
weitergibt falls dieser erreichbar ist. Falls nicht, leitet er diese auf
den lokalen Webserver weiter. Der DNS-Dienst muss zwingend alle Anfragen
auflösen, damit der Browser immer eine Webseite zur Anzeige bekommt und
nie eine Fehlerseite anzeigt.
Da ich mich mit Netzwerken nicht so gut auskenne ist nun meine Frage an
euch, ob jemand einen eleganteren Weg kennt wie man ein solches Problem
lösen könnte.
Danke im Voraus und Grüsse
Philipp
Philipp K. schrieb:> Wenn der Client keine Verbindung zum Server aufbauen kann, soll dies dem> Benutzer optisch ansprechend mittels einer Webseite gezeigt werden. Auf> keinen Fall darf jemals eine Fehlerseite z.B. ERR_NAME_NOT_RESOLVED des> Browsers angezeigt werden. Denn ohne F5 Taste zum aktualisieren kommt> man von einer solchen Seite nie wieder weg.
Und wie kommst du von der Fehlerseite wieder weg?
Was willst du denn überhaupt machen? Eine Webseite anzeigen und
periodisch neu laden, ohne sonstige Eingriffsmöglichkeiten des
Benutzers? Dann lade den Seiteninhalt über JavaScript und schaue nach,
ob was sinnvolles zurückkommt.
DNS Anfragen werden üblicherweise vom Betriebssystem gecacht.
Das bedeutet Du machst eine Auflösung, Dein Server ist gerade da, gibt
dem Client seine IP zurück und beim nächsten Aufruf der Seite macht der
Client nicht nochmal eine DNS-Anfrage weil er die Antwort ja schon
kennt.
Was Jan vorschlägt klingt vernünftiger ...
Das wird so nicht zuverlässig funktionieren. Wenn der Browser die IP
hat, fragt er nie wieder beim DNS nach. Beim Browserstart funktioniert
alles. Eine Stunde später fällt der Server aus. Und dein Browser benutzt
weiter die alte IP.
Ich würde es direkt im HTML/Javascript machen. Entweder traditionell mit
Frames. Nur der innere Frame wird neu geladen. Die Navigation bleibt
stehen. Kannst auch einen Javascript-Mechanismus bauen; wenn sich der
innere Frame nicht bei der Navigation anmeldet, wird nach einem Timeout
eine Fehlerseite geladen.
Oder du machst es modern als Single-Page-Webapp. Es wird nur eine
einzige Htmp-Seite geladen. Die holt nur Rohdaten vom Server und ändert
mit Javascript ihren Inhalt.
-------- snippet off ----------
Die Hilfsseite liegt auf dem Client, Dein Browser fragt immer nur die
lokale Hilfsseite ab. Wird komplizierter bei mehreren Seiten, dann
müsste die Hauptseite auf dem Server absolute Pfade zu den anderen
Seiten auf dem Server enthalten anstelle von relativen Pfaden.
Hallo zusammen
Dass das mit DNS nicht so richtig funktioniert leuchtet mir nun ein.
Die Python Lösung hat meiner Meinung nach den Nachteil, dass diese nicht
mehr greift, sobald die Verbindung einmal zustande gekommen ist.
Bei der Javascript/Frames Lösung habe ich ein bisschen bedenken, da die
Webseite auf dem Server bereits diverse Javascripts & AJAX verwendet. Ob
das Konfliktfrei funktionieren wird weiss ich nicht.
Die Variante mit einem Proxy gefällt mir bis jetzt am besten. Ich werde
das mal mit squid versuchen, oder gibt es etwas einfacheres?
Noch einer schrieb:> Das wird so nicht zuverlässig funktionieren. Wenn der Browser die IP> hat, fragt er nie wieder beim DNS nach.
Der Browser wird keine IPs cachen, das macht das Betriebssystem - bei
Windows abzufragen mit "ipconfig /displaydns".
Ich hoffe doch, dass dieser Cache die Lifetime "TTL" berücksichtigt, der
DNS also eine TTL von nur wenigen Sekunden liefern sollte.
Manfred schrieb:> Der Browser wird keine IPs cachen, das macht das Betriebssystem - bei> Windows abzufragen mit "ipconfig /displaydns".
Mindestens Chrome cached definitiv selbst DNS-Einträge unabhängig vom
Betriebssystem.
noch eine Lösung:
bluppdidupp schrieb:> Mindestens Chrome cached definitiv selbst DNS-Einträge unabhängig vom> Betriebssystem.
Nö, gerade ausprobiert:
mit Chromium www.mikrocontroller.net aufgerufen, Seite reloaded: geht
/etc/hosts manipuliert:
127.0.0.1 www.mikrocontroller.net
Seite reloaded: geht nicht
/etc/hosts manipuliert (auskommentiert):
# 127.0.0.1 www.mikrocontroller.net
Seite reloaded: geht nicht
Daraus folgt: wenn man per Programm in einer Dauerschleife (z.B. alle 30
Sekunden) die /etc/hosts manipuliert (abhängig, ob Server erreichbar
oder nicht), kann das vom TE erstellt Problem gelöst werden.
Keine Ahnung ob Chrome und Chromium da abweichend sind oder was die
genauen Umstände sind, ich bin bei Chrome unter Windows auf jedenfall
davon auch betroffen:
https://superuser.com/a/203702
Der dnsmasq vom Android liest die /system/etc/hosts genau
einmal beim Starten. Danach kann Mann da schreiben was Mann will...
Was zuverlaessig funktioniert, ist per iptables den Request
im Fehlerfall an die passende Adresse zu schicken.
Im Beispiel lauscht lokal auf dem Androiden ein Webserver
auf dem Port 1080.
1
su -c iptables -t nat -A OUTPUT -p tcp -d 1.0.0.1 --dport 80 -j DNAT --to-destination 127.0.0.1:1080
Das su muss Mann sich selber kompilieren. Die su aus Androidpaketen
kennen die Option "-c" oft nicht.
Ein:
1
su -c iptables -t nat -D OUTPUT 1
stellt die normalen Verhaeltnisse wieder her.
Ein Script das die Erreichbarkeit des richtigen Servers
pollt, schaltet dann dazwischen um.
trostpreis schrieb:> Das könnte man gut mit Python lösen, mal schnell "hingerotzt":>
1
>
2
> #!/usr/bin/python
3
> # -*- coding: utf-8 -*-
4
>
5
> import urllib2, os
6
>
7
> while 1
8
>
9
> try:
10
> seite = urllib2.urlopen(http://pfad/zum/server/seite.htm).read()
11
> except:
12
> seite = open(/home/user/hilfsseite.htm).read()
13
>
14
> os.system("/usr/bin/chromium")
15
>
16
>
ich würde das ähnlich machen - an der netzwerkconfig rum zu schrauben
ist keine gute idee, denn das netzwerk ist nicht der grund warum der
server nicht erreichbar ist.
es ist, wie es in obigem code beschrieben wird: eine resource soll
geladen werden, und wenn das nicht funktioniert soll eine meldung
ausgegeben werden. wenn es ein normales GUI programm wäre, und eine
datei geöffnet werden sollte, würde auch keiner auf die idee kommen im
fehlerfall fix mal einen hardlink zu setzen um die nicht ladbare datei
durch eine dummy datei zu ersetzen.
meine idee wäre lokal auf dem client einen http-server mit php zu haben,
die index.php hat im html-header "reload alle 10 sec" stehen (genaue
syntax weiß ich nicht auswendig, bin kein web entwickler :).
im php-script wird versucht die externe resource zu laden, und wenn das
nicht funktioniert, wird eine interne resource geladen, oder
fehlermeldung ausgegeben.
der browser auf dem client lädt die index.php einmal, und dann halt
immer wieder - der inhalt der seite wird durch das php-script bestimmt.
und noch was zu obigem code: es wäre von vorteil wenn man der
urllib-klasse sagen könnte wie lange der timeout sein darf, nicht dass
das laden der server-seite 30 sekunden lange versucht wird.
Abgesehen davon das ich $irgendwas mit Chrom nicht mehr instinktiv als
embedded ansehen würde (vielleicht haben sich die Zeiten ja geändert).
Möchte ich nochmal die Lösung mit den Proxy ansprechen. Klar kann man
das sicher auch in Python machen und das wäre wahrscheinlich auch mein
erster ansatz das mit den try/except umzusetzen.
Aber wenn es ein Produkt werden soll, wäre meine Empfehlung den Nginx,
alternativ den lighttpd als Proxy auf den Client zu installieren.
Beide habe ich schon erfolgreich in embedded Projekten eingesetzt und
hätten im Vergleich zu der Python Lösung den charmanten Vorteil nur noch
Konfiguriert werden müssen.
Beide vor allen aber der Nginx haben sich schon 1000 Fach als Proxy
bewährt. Bei der Python Lösung fängst du von 0 an und musst selbst
erstmals alle Fehler und Fallen finden und beheben.
Abgesehen davon hat so eine Proxylösung, egal ob Homebrew Python oder
Nginx denn Vorteil das auch fälle wie DNS geht, Webserver weg gleich mit
gecovert werden.
> an der netzwerkconfig rum zu schrauben
Das tut es ja nicht.
Der Request wird von der nat/Output-Regel nur an ein anderes Ziel
geschickt. Das funktioniert in einer anderen Anwendung schon heute
bestens und zuverlaessig.
An der Netzwerkkonfiguration wird dadurch nichts geaendert.
Irgendwelche Cachingprobleme treten dabei nicht auf.
Die Dummy/Fehler-Webseite muss natuerlich auch passende
http-Parameter zurueckgeben.
Kommerzielle Loadbalancer machen das auch nicht viel anders.
Wer aber nur in PHP frickeln kann, wird es wohl damit versuchen.