Zustandsmaschine

Zustandsmaschinen definieren Aktionen in Abhängigkeit von vorhergehenden Aktionen bzw. eingenommen Zuständen. Sie finden immer da Verwendung, wo es eine endliche Anzahl von Zuständen und Aktionen geben kann. Dies sind unter Anderem: Datenparser, Maschinensteuerungen, Verbindungsprotokolle oder auch Spielelogik.

Beispiel (Quellcode): statemachine.cpp
Download (Quellcode): statemachine.zip

Beschreibung

Beispiel für eine Zustandsmaschine zum Verbindungsaufbau Wie bereits erwähnt, benutzen Zustandsmaschinen die vorhergehenden Zustände bzw. den letzten Zustand, um eine Aktion im aktuellen Kontext durchführen zu können. Meist wird eine Aktion durch eine Eingabe in das Zustandssystem ausgelöst. Da nur eine limitierte Anzahl von Aktionen möglich ist, können je nach Zustand/Kontext verschiedene Dinge verboten, erlaubt oder in ihrer Funktion verändert sein. Dies lässt sich gut für Sicherheitsfunktionen verwenden (zum Beispiel für eine Authentifizierung).

Eine Zustandsmaschine kann von einem Zustand in einen Anderen überführt werden, dies muss nicht zwangsläufig der nächste Zustand in der Liste sein. Daher ist es Ratsam, vor dem Design einer solchen, alle möglichen Zustände und deren Verknüpfung in Abhängigkeit der Dateneingabe, zu Zeichnen oder aufzuschreiben. Wichtig ist auch die Frage: "Was passiert bei falschen Dateneingaben?"

Je komplexer die Verknüpfungen, desto leichter kann ein Fehler unter bestimmten Dateneingaben zu fehlerhaften oder ungewollten Zuständen führen. Daher ist es empfehlenswert, eine Zustandsmaschine möglichst einfach zu halten. Zur Verringerung der Komplexität ist es möglich, mehrere Zustandsmaschinen für verschiedene Aufgaben hintereinander zu schalten. (Als Beispiel Protokollparser und dahinter höhere Protokolllogik, jeweils extra verpackt.)

Als Dateneingabe lassen sich jegliche Daten und Metadaten verwenden. Oft ist unter Anderem die Zeit eine Quelle zur Zustandsänderung und Aktionsauslösung.

Durch den Beispielcode

Der Beispielcode, enthält eine Klasse (C++), die eine Beispielauthentifizierung für einen Datenstrom darstellen soll:

  • der Konstruktor

    CStateMachine() : m_nCurrentState(STATE_CONNECT) {}
    26
    

    Beim Erzeugen der Klasse, wird der Status auf "frisch Verbunden" gesetzt.

  • Dateneingabe

    void Input(const std::string& sInput)
    29
    

    Ein Datensatz wird in die Zustandsmaschine zur Verarbeitung gegeben.

  • Zustandsausgabe

    void Output()
    66
    

    Gibt den aktuellen Zustand auf den Bildschirm aus.

Codeanmerkungen

  1. Die Aufrufparameter des Programms bilden Datensätze die der Zustandsmaschine zugeführt werden:

    for(int n=1; n<argc; n++)
    96
    

    So ergibt

    ./statemachine hello user mypassword data1 data2 data3 disconnect
    

    die Ausgabe

    State machine example...
    
       (  1)      hello: CONNECT       -> USERNAME     
       (  2)       user: USERNAME      -> PASSWORD     
       (  3) mypassword: PASSWORD      -> AUTHENTICATED
       (  4)      data1: AUTHENTICATED -> AUTHENTICATED
       (  5)      data2: AUTHENTICATED -> AUTHENTICATED
       (  6)      data3: AUTHENTICATED -> AUTHENTICATED
       (  7) disconnect: AUTHENTICATED -> DISCONNECTED