Ich schreibe den Code neu, um einige eingebettete Kommunikationen zu verarbeiten, und im Moment ist die Protokollverarbeitung in einer While-Schleife mit einer großen Case/Switch-Anweisung implementiert. Diese Methode erscheint mir ein wenig unhandlich. Was sind die am häufigsten verwendeten Flusssteuerungsmethoden für die Implementierung von Kommunikationsprotokollen?
Antworten
Zu viele Anzeigen?Es hört sich so an, als ob die "while + switch/case" eine Statemachine-Implementierung ist. Ich glaube, dass eine gut durchdachte Statemachine oft der einfachste und lesbarste Weg ist, ein Protokoll zu implementieren.
Wenn es um Statemachines geht, gehört es dazu, einige der traditionellen Programmierregeln zu brechen. Regeln wie "jede Funktion sollte weniger als 25 Zeilen lang sein" funktionieren einfach nicht. Man könnte sogar argumentieren, dass Statemachines verkappte GOTOs sind.
Für Fälle, in denen Sie ein Feld in einem Protokollkopf verwenden, um zur nächsten Verarbeitungsstufe für dieses Protokoll zu gelangen, können Arrays mit Funktionszeigern verwendet werden. Sie verwenden den Wert aus dem Protokollkopf, um in das Array zu indizieren und die Funktion für dieses Protokoll aufzurufen.
Sie muss alle möglichen Werte in diesem Array verarbeiten, auch solche, die nicht gültig sind. Irgendwann werden Sie ein Paket erhalten, das einen ungültigen Wert enthält, entweder weil jemand einen Angriff versucht oder weil eine zukünftige Revision des Protokolls neue Werte hinzufügt.
Wenn es sich um ein einziges Protokoll handelt, ist eine switch/case-Anweisung möglicherweise die beste Lösung. Sie sollten jedoch alle einzelnen Nachrichten-Handler in ihre eigenen Funktionen aufteilen.
Wenn Ihre switch-Anweisung Code enthält, um die Nachrichten tatsächlich zu verarbeiten, sollten Sie sie besser herausbrechen.
Wenn es sich um mehrere ähnliche Protokolle handelt, könnten Sie eine Klasse erstellen, die jedes Protokoll auf der Grundlage derselben abstrakten Klasse behandelt, und wenn die Verbindung eingeht, könnten Sie feststellen, um welches Protokoll es sich handelt, und eine Instanz der entsprechenden Handler-Klasse erstellen, um die Kommunikation zu dekodieren und zu behandeln.
Ich denke, das hängt weitgehend von der Sprache ab, die Sie verwenden, und davon, welche Art von Datensatzobjekten Ihnen zur Verfügung steht.
In Python könnten Sie zum Beispiel ein Dictionary-Objekt mit allen verschiedenen Verarbeitungsanweisungen erstellen und dieses einfach durchlaufen, um die richtige aufzurufende Methode/Funktion zu finden.
Case/Switch-Anweisungen sind keine schlechten Dinge, aber wenn sie riesig werden (wie sie mit massiven Mengen von Protokoll-Handlern können), dann können sie unhandlich zu arbeiten.