Mein Kunde auch. Er entwickelt eine Smartphone-Anwendung („App“) und die dazu passende Server-Komponente im Internet („Cloud“). Beides dient der Steuerung eines IoT-Geräts, nennen wir es „Getränkeautomat“. Möchte der häusliche Anwender sich ein Getränk zubereiten, kann er sich dabei von der App unterstützen lassen, wenn er möchte. Zu diesem Zweck verfügt der Getränkeautomat über ein WLAN-Modul, über das er eine TCP-Verbindung zum Cloud-Server aufbaut. Die Smartphone App macht das genauso.
Nun kann es sein, dass in der Cloud eine neue Firmware für den Getränkeautomaten bereitliegt. Der Anwender erfährt das über seine App und kann den Firmware Download anstoßen oder auf die kommende Nacht verschieben. Dann macht es auch nichts, wenn der ganze Vorgang eine Viertelstunde dauert. Blöd ist nur, wenn der Vorgang irgendwann abbricht. Und das passierte meinem Kunden regelmäßig beim Test der Download-Funktion.
Wir haben uns das dann gemeinsam mit dem Protokollanalysator angesehen: Der Server schickte immer genau so viele Bytes, wie ihm der Getränkeautomat vorgab. Wir erinnern uns: Eine grundlegende Idee hinter TCP ist, dass der Sender eine größere Zahl von Paketen senden darf, ohne auf eine Bestätigung warten zu müssen. Die Anzahl der ohne Bestätigung gesendeten Bytes (das „TCP Window“) soll größer sein als das Produkt aus Bitrate und Round Trip Time. Unter dieser Bedingung kann eine Leitung vollständig ausgelastet werden.
Das war hier ganz klar nicht der Fall. Der Getränkeautomat signalisierte immer nur wenige Kilobyte Empfangspuffer (das „Receiver Window“). Und mit jedem empfangenen Paket wurde dieser Puffer kleiner, um schließlich den Wert 0 anzunehmen („Zero Window“). Der Automat zeigte damit an, dass er zeitweise überhaupt keine Pakete annehmen konnte. Solche Zustände hielten manchmal bis zu zwei Sekunden (!) an.
Regelmäßig verkleinerte der Automat sogar sein Receiver Window, ohne dass Daten empfangen wurden. Das Ergebnis war, dass ein Teil der vom Server bereits abgeschickten Bytes verloren gingen, weil der Automat sie nun doch nicht mehr annehmen konnte.
Ich habe diese Sachverhalte schließlich mit dem Programmierer des WLAN-Moduls diskutiert. Dabei ist folgendes herausgekommen:
- TCP ist auf dem WLAN-Modul implementiert; so finde ich es auch immer wieder im Umfeld von Fertigung und Automation vor.
- Das WLAN-Modul ist ein „Embedded System“, beinhaltet also einen Mikrorechner. Die Ressourcen dieses Mikrorechners sind äußerst begrenzt.
- Insbesondere steht wenig Rechenleistung zur Verfügung. Die Entschlüsselung des Datenstroms (hier SSL/HTTPS) ist somit der Flaschenhals bei der Übertragung.
- Darüber hinaus steht wenig Speicher zur Verfügung. Die dynamische Speicherverwaltung muss dem TCP immer wieder Speicher wegnehmen und für andere Zwecke verwenden.
- Die Größe des Empfangspuffers, die das Modul signalisiert, gibt dem Sender keine Garantie, dass dieser Speicher noch zur Verfügung steht, wenn seine Pakete schließlich am Empfänger ankommen. Ich konnte das nicht glauben und habe gleich im einschlägigen Standard (RFC 793) nachgelesen: Es stimmt, das TCP Receiver Window bezeichnet einen aktuellen Zustand, ohne Garantie für die Zukunft.
Fazit: In den vergangenen Jahren habe ich in meinen Seminaren versucht, den Teilnehmern ein Verständnis für die TCP-Übertragung in Netzen mit langer Laufzeit und hoher Bitrate („Long Fat Networks“) zu vermitteln. Hier lässt sich einiges mittels Parametrierung des TCP optimieren. Im Gegensatz dazu scheinen die Grenzen der IoT-Welt eher in den Endgeräten zu liegen.
Von dem Beispiel des Getränkeautomaten lässt sich noch viel mehr lernen, z.B. über sinnvolles Management von Software-Projekten. Jedenfalls stellten sich die Abbrüche als Programmierfehler heraus. Was bleibt, ist die schlechte Performance des Firmware Download. Aber solange das nachts passiert und der Anwender zum Frühstück mit frischen Getränken begrüßt wird, macht das nichts. Ich für meinen Teil lasse mir Getränke bis auf weiteres auch ohne App und Cloud schmecken.