Hallo,
ich habe hier ein Projekt übernommen, bei dem Messdaten aus einem µC an
ein PC Anwendung übermittelt werden.
Der PC sendet ein Paket mit den gewünschten Daten an den µC und dieser
antwortet dementsprechend.
Das ganze passiert über einen Webserver im µC. Der PC sendet also einen
http request, der µC die http response.
Jetzt gibt es in der Anwendung auch eine streaming Funktion mit der
zyklisch Daten ausgelesen werden können 1s oder langsamer.
In Wireshark ist mir dann aufgefallen, dass bei jeder Message, die
ausgetauscht wird die Verbindung geöffnet und wieder geschlossen wird.
Ist das ein normales Verhalten?
Kennt jemand ein Sequenzdiagramm welches eine Anfrage an einen webserver
bis auf TCP Ebene herunter darstellt? Ich konnte (wohl mangels
Suchbegriffe) nichts geeignetes finden.
In meinen Augen ist ein HTTP Server nicht für solche streaming
Angelegenheiten geeignet, besser direkt ein TCP Socket. (Nun ja, ist
aber so umgesetzt und vorhanden.)
Unabhängig von dieser Applikation betrachtet:
Ich kann mir auch vorstellen, dass beobachtetes Verhalten korrekt ist,
da die Daten ja geliefert wurden und vom internetsurfenden PC User erst
gelesen werden müssen. Bevor das immer ins Timeout rennt, wird die
Verbindung direkt geschlossen.
Grüße
Harry
> Ist das ein normales Verhalten?
Ja.
Suchwort "HTTP Keep-Alive" für Optionen wie das zu umgehen ist, und
welche Voraussetzungen der Server dafür mitbringen muss.
> In meinen Augen ist ein HTTP Server nicht für solche streaming> Angelegenheiten geeignet,
Geht schon,
früher per "long-poll" und andere Hacks, heute nimmt man Websockets. Da
läuft der Verbindungsaufbau auch über HTTP, schaltet dann aber
zwischendurch auf ein anderes Protokoll und lässt die TCP-Verbindung am
Leben.
Εrnst B. schrieb:> Suchwort "HTTP Keep-Alive"
Ah, das scheint genau das zu sein was ich brauche oder besser gleich nur
TCP.
Εrnst B. schrieb:> Websockets
Wird beim uC leider nicht mitgeliefert. Da der Webserver sonst keine
Funktion besitzt, denke ich es ist das beste auf reine TCP Sockets
umzusteigen. Das schont auch die Ressourcen insgesamt.
Danke für deine Antwort.
Harry schrieb:> In Wireshark ist mir dann aufgefallen, dass bei jeder Message, die> ausgetauscht wird die Verbindung geöffnet und wieder geschlossen wird.> Ist das ein normales Verhalten?
Beim HTTP 1.0 Protokoll muss das so sein. Das Trennen der Verbindung
kennzeichnet das Ende der Response.
Bei HTPP 1.1 wurde das geändert. Dort kann der Server wahlweise
a) durch einen Content-Length Header die Größe der folgenden Response
melden, oder
b) Durch einen Chunk der Größe 0 das Ende der Response markieren.
Die Verbindung kann danach offen bleiben und für den nächsten Request
verwendet werden. Neu seit HTTP 1.1 ist auch, dass der Client mehrere
Requests direkt hintereinander senden kann, die der Server dann
nacheinander abarbeitet.
Die Wikipedia verweist auf die Spezifikationen, die ich im groben und
ganzen verständlich finde. Auf deren Basis habe ich die QtWebApp
Bibliothek (HTTP Server in C++) geschrieben. Antworten zu Detailfragen
habe ich überwiegend auf Webseiten von Microsoft gefunden.
https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP/1.0
Harry schrieb:>> Websockets> Wird beim uC leider nicht mitgeliefert.
Ist ein Aufsatz auf HTTP. Wenn dein Mikrocontroller eine HTTP 1.1 Server
Funktion hat, kannst du den Websocket-Aufsatz selbst implementieren.
Großartig kompliziert sieht das nicht aus, ich hab es allerdings noch
nicht versucht.
Wenn der Client ein Web-Browser sein soll, hast du kaum eine andere
Wahl, als Websockets zu verwenden. Für selbst geschriebene Clients ist
je nach Anwendung TCP oder UDP einfacher. TCP würde ich nur nehmen, wenn
Lückenlose Übertragung wichtig ist. UDP stellt das nicht sicher, ist
dafür schneller und überträgt gleichmäßiger (gerät bei Störungen weniger
ins Stocken).
Auch dir danke für die Antwort.
Ich denke trotzdem, dass ich die ganze Geschichte auf TCP Sockets
umbauen werde.
Es muss kein Webserver laufen und es muss auch kein ping pong streaming
stattfinden.
Einmal den Stream starten und dann mit "eigenen keep alive" Paketen
immer wieder mal "den watchdog resetten".
Das scheint mir sinnvoller. Dann hat man auch die Zeitbasis aus dem uC
und nicht die vom PC.
Harry schrieb:> In meinen Augen ist ein HTTP Server nicht für solche streaming> Angelegenheiten geeignet, besser direkt ein TCP Socket. (Nun ja, ist> aber so umgesetzt und vorhanden.)
MQTT wurde genau für solche Anwendungen erfunden.
Stefan ⛄ F. schrieb:> Für Streaming? Entweder hast du den Harry nicht verstanden oder ich> dich.
Scheint eher, als hättest du nicht richtig gelesen.
Harry schrieb:> ich habe hier ein Projekt übernommen, bei dem Messdaten aus einem µC an> ein PC Anwendung übermittelt werden.> Der PC sendet ein Paket mit den gewünschten Daten an den µC und dieser> antwortet dementsprechend.
Harry schrieb:> Aber für MQTT brauche ich doch noch einen Broker. Für Cloud-Anwendungen> ok, aber bei P2P reicht TCP doch völlig. Oder liege ich hier falsch?
Wenn du den PC man neu starten musst (Windows Update), gehen dir ohne
Zwischenspeicher Daten verloren. Bei einem MQTT Broker hast du das
Problem nicht, wenn wir mal davon ausgehen dass er auf einer weitgehend
wartungsfreien Maschine (z.B. unter Linux) läuft. So ein Broker kann
auch redundant aufgebaut sein.
Harry schrieb:>> Websockets>> Wird beim uC leider nicht mitgeliefert.
Dann nimm SSE (Server-Sent Events). Unidirektional, und sehr einfach
manuell zu implementieren.
Clemens L. schrieb:> Dann nimm SSE (Server-Sent Events). Unidirektional, und sehr einfach> manuell zu implementieren.
Das ist die falsche Übertragungsrichtung.
Harry schrieb:> Ist das ein normales Verhalten?
Für HTTP/1.0 ja, für HTTP/1.1 (insbesondere einfachere Implementationen)
auch.
> In meinen Augen ist ein HTTP Server nicht für solche streaming> Angelegenheiten geeignet, besser direkt ein TCP Socket. (Nun ja, ist> aber so umgesetzt und vorhanden.)
HTTP hat den Vorteil, dass es durch sämtliche Firewalls durchgeht, von
allen Middleware-Boxen unterstützt wird und auch sonst als "das eine
Protokoll" gesehen wird. Je nach Paranoia der IT-Abteilung wird auch
schonmal alles andere weggefiltert.
Wenn du schon eine funktionierende HTTP-Lösung hast, würde ich mir erst
recht überlegen, ob ich davon weggehen wollen würde. Weil du dir damit
zukünftige Probleme beschaffst.
Muss es denn HTTP sein?
Ich habe bisher immer auf µC Seite mit LwIP ein TCP-Server-Socket
programmiert.
Auf PC-Seite dann eine Anwendung die eine Verbindung aufbaut.
Der µC schickt dann seine Messdaten.
Im einfachsten Fall Zeilenweiße in ASCII codiert.
Hab's aber auch schon Binär gemacht und ein Anwendungsprotokoll dafür
implementiert.
Verbindung bleibt solange bestehen, bis die PC-Anwendung sie wieder
schließt.
C.K. schrieb:> Muss es denn HTTP sein?
Was ist daran so schlimm? Weil es Web-Technologie ist?
C.K. schrieb:> Der µC schickt dann seine Messdaten.>> Im einfachsten Fall Zeilenweiße in ASCII codiert.
Also der Server sendet z.B.:
1,2344 <END_OF_LINE>
2,1234 <END_OF_LINE>
3,4234 <END_OF_LINE>
....
Sinmples ASCII-Protokoll, so habe ich Dich verstanden.
Und nun, die komplizierte Änderung für den Server, wenn er als
HTTP-Server fungieren soll, sendet der Server:
HTTP/1.0 200 OK <END_OF_LINE>
Content-Type: text/event-stream <END_OF_LINE>
<END_OF_LINE>
data: 1,2344 <END_OF_LINE>
<END_OF_LINE>
data: 2,1234 <END_OF_LINE>
<END_OF_LINE>
data: 3,4234 <END_OF_LINE>
<END_OF_LINE>
...
Und schon hast Du einen HTTP-Server programmiert:
Einmal nach Verbindungsaufbau einen kleinen Header senden, danach vor
jeden Messwert den String "data:" senden, und die einzelnen Messwerte
durch Leerzeilen unterteilen.
Fertig sind die Server-Sent-Events!
Plötzlich hast Du alle Vorteile von HTTP:
- Beinahe grenzenlose Angebot an Tooling
- Für jeden erdenkliche Programmiersprache gibt es Bibliotheken
um den Eventstream zu lesen
- Du kannst Proxies und Reverse-Proxies verwenden
- und, und, und.
Unbekannt U. schrieb:> Was ist daran so schlimm? Weil es Web-Technologie ist?
Ich stelle mir vor, dass ein embedded webserver ressourcenhungriger ist
als ein reiner TCP Socket.
Berichtigt mich bitte, falls der Unterschied vernachlässigbar gering
ist.
Harry schrieb:> Ich stelle mir vor, dass ein embedded webserver ressourcenhungriger ist> als ein reiner TCP Socket.
Kommt ganz drauf an, wie viel du vom HTTP Protokoll implementieren
willst.
Nach deiner eigenen Aussage willst du, dass der PC (Client) ein Kommando
sendet und der Server daraufhin antworten liefert. Das ist eigentlich
genau der Grundgedanke von HTTP. Die einzige Ressource die du dafür
brauchst ist ein Zeilenpuffer (wohl weniger als 100 Bytes). Du kannst
sogar ein und den selben Puffer abwechselnd zum Senden als auch zum
Empfangen benutzen.
Siehe
http://stefanfrings.de/mikrocontroller_buch/Einstieg%20in%20die%20Elektronik%20mit%20Mikrocontrollern%20-%20Band%202.pdf
Kapitel 10, dort ist das Protokoll beschrieben, nur die Basics die du
brauchst.
Klar kannst du auch dein eigenes Protokoll entwickeln, ich bezweifle
allerdings das es deutlich einfacher wird. Auf jeden Fall wird es
schwieriger zu testen. Ein Web-Browser zum Testen ist wohl kaum an
Einfachheit zu toppen.
http://stefanfrings.de/mikrocontroller_buch/Einstieg%20in%20die%20Elektronik%20mit%20Mikrocontrollern%20-%20Band%203.pdf
Kapitel 13 zeigt, wie man einen einfachen HTTP Server auf einem
Mikrocontroller implementieren kann.
Auf http://stefanfrings.de/esp8266/index.html#tcpsketch findest du ein
Arduino Beispiel mit TCP Socket ohne HTTP. Wesentlich einfacher sieht
das dort nicht aus. Aber entscheide selbst.
frage wäre wie wichtig die messdaten sind ^^
sonst ginge auch UDP broadcast
einfach einen eigenen header mit einer art sequenznummer und timing
mitsenden
damit kann ein/mehrere empfänger auch interpolieren wenn er mal was
verpasst hat
Stefan ⛄ F. schrieb:>> Dann nimm SSE (Server-Sent Events). Unidirektional, und sehr einfach>> manuell zu implementieren.>> Das ist die falsche Übertragungsrichtung.
Vom Embedded-Webserver an den PC ist die richtige Richtung.
Clemens L. schrieb:> Vom Embedded-Webserver an den PC ist die richtige Richtung.
Ja, ich dachte bis dahin, dass Harrys µC die Verbindung zum PC aufbauen
soll, also dann der HTTP Client ist. Aber in seinen folgenden Beiträgen
wurde klar, dass er es anders herum machen will. Passt schon.
Stefan ⛄ F. schrieb:> Nach deiner eigenen Aussage willst du, dass der PC (Client) ein Kommando> sendet und der Server daraufhin antworten liefert. Das ist eigentlich> genau der Grundgedanke von HTTP.