Wo soll ein Protokoll mit boost :: asio implementiert werden?

8

Ich versuche ein einfaches serielles Port-Protokoll zu implementieren. Es geht so:

  1. verwirft alle Daten, bis 0xff empfangen wurde
  2. Lese-Header (Knotenadresse und Datenlänge, 4 Byte)
  3. Daten lesen (max. 64 Bytes)
  4. lesen Sie crc
  5. verarbeitet das empfangene Paket
  6. Antwort senden
  7. wenn 0xff angezeigt wird, auch wenn es nicht wie in der Mitte der Daten erwartet wird, bedeutet dies, dass ein neues Paket empfangen wird

Ich kann dies implementieren, indem boost::asio::serial_port mit boost::asio::read() ein einzelnes Byte liest und dieses Byte verarbeitet, wenn es empfangen wird. Obwohl das funktioniert, habe ich mich gefragt, ob es einen "boost" -artigen Weg gibt, dies zu tun?

Ich habe boost::asio::read_until() zum Lesen gelesen bis 0xff , aber dann weiß ich nicht, wie ich die Daten verwerfen soll. Speichern der Daten in einem Puffer und dann nicht den Puffer verwenden scheint ein wenig verschwenderisch.

Ich kann boost::asio::read_until() zum Lesen bis zum Ende des Pakets verwenden, aber dann muss MatchCondition Zugriff auf den Puffer (den Header des Pakets) haben. Es scheint, dass MatchCondition nur einen Iterator für das erste und letzte Byte erhält, das kürzlich empfangen wurde.

Auch die mit boost::asio::read() empfangenen Daten landen in stream_buf und ich muss die empfangenen Daten in ein Packet -Objekt analysieren. Ich kann das in Packet in einem separaten ParsePacket -Objekt parsen oder irgendwie mit boost::asio integrieren (etwas wie boost::asio::read(serial, myPacket); , wobei myPacket ein Packet -Objekt ist)

Wenn 0xff irgendwo in den empfangenen Daten gesehen wird, bedeutet dies, dass ein neues Paket gestartet wird. Wenn also 0xff empfangen wird, muss es alle zuvor empfangenen Daten vergessen und ein neues Paket empfangen.

Ich plane die Verwendung asynchroner Operationen und das Hinzufügen von Timeouts.

Meine Frage ist also: Wo soll ich ein solches Protokoll implementieren? Oder allgemeiner, wo ein Protokoll mit boost::asio implementiert werden soll. Ich suche nicht nach funktionierendem Code, sondern nach Ratschlägen darüber, wo das Protokoll implementiert werden soll und welche boost::asio -Funktionalität zu verwenden ist.

Aktualisierung:

In diesem Fall wird keine Flusssteuerung (Hardware oder Software) verwendet.

    
rve 18.11.2011, 06:53
quelle

2 Antworten

2

Zunächst möchte ich Ihnen, wie @Autopulated in Kommentaren gezeigt hat, vor der Verwendung von Trennzeichen (Ihre 0xFF) in binären Protokollen warnen. Es ist eine gefährliche Technik (bringt viel Zweideutigkeit) und erfordert komplizierte Implementierungen. Selbst wenn Sie garantieren können, dass Ihre Daten keine 0xFF-Bytes enthalten, können Sie dies beim CRC-Feld nicht tun.

Ich würde empfehlen, sich nicht mit Trennzeichen zu beschäftigen und sich auf ein einfaches und vorhersagbares Binärprotokoll zu konzentrieren: [packet][packet]... wo [packet] = [node address:X][data length:4][data:data length][CRC:1]

Das Senden solcher Pakete kann wie folgt aussehen:

%Vor%

Empfangen:

%Vor%

Bitte beachten Sie, dass in diesem Beispiel angenommen wird, dass beide Peers die gleiche Endgültigkeit haben.

Ich habe diesen Code hier geschrieben, also erwarte nicht, dass er richtig ist, benutze ihn nur als Idee.

    
Andriy Tylychko 18.11.2011 10:07
quelle
0

Bei der Implementierung von Protokollen habe ich zuvor State-Maschinen sehr nützlich gefunden.

Obwohl ich asio nicht verwendet habe, kann diese Technik hier anwendbar sein.

Diese können in C ++ als enum , als Schleife und als switch wie folgt implementiert werden:

%Vor%

Sie müssten mehr Flags hinzufügen, um Ihren Fortschritt im Protokoll zu verfolgen.

Sie können auch nach boost::statechart suchen Implementieren der Zustandsmaschine.

    
Silas Parker 18.11.2011 08:56
quelle

Tags und Links