シリアル通信のバイトエスケープ
区切り文字がデータにもなるのはなぜか?
シリアル受信側が認識するのは文字ですが、アプリケーションはメッセージを識別する必要があります。SLIPはペイロード内のC0とDBを2バイトのシーケンスでエスケープし、エスケープされていないENDでパケットを区切れるようにします。受信側は読み取りをまたいで状態を保持しながら、逆変換します。これらの特定の値はSLIPに固有のものであり、それ自体で誤り検査やセキュリティを提供するわけではありません。
文字とパケットの違い
文字の境界だけでは、アプリケーションのメッセージを識別できません。
特殊なデータをエスケープする
SLIPはペイロード内の特殊なバイトを2バイトのシーケンスで表します。
状態を保持する
読み取りがDBの直後で終わっても、パーサーはエスケープ状態を保持する必要があります。
両端と保護範囲を明確にします。
実際のプロトコルと設定を確認します。
許可を得たうえで無害なデータを使用してテストします。
選定・検証チェックリスト — 展開
プロトコルとキャプチャの階層を確認し、通常のバイトと特殊なバイトをテストしてください。許可された環境で、分割された読み取り、重複するマーカー、エラー処理を検証してください。
シリアル回線はバイトのストリームを届けます。受信プログラムは、メッセージの終わりをどのように認識するのでしょうか。1つの方法は、特定のマーカーを予約することです。しかし、測定値やファイルにも同じバイト値が含まれる可能性があり、そのまま送信すると終端と誤認されるおそれがあります。バイトエスケープは、この曖昧さを解消します。これを理解するには、ボーレートだけを見るのではなく、文字の受信、パケットの境界、アプリケーション上の意味を分けて考える必要があります。

正しい文字が受信されても、自動的にパケットになるわけではない
一般的な非同期シリアルインターフェースは、スタートビット、データビット、ストップビットを使って文字を識別します。文字がプログラムに届くと、それらはバイト列になります。受信側が温度測定値の始まりと終わりを自動的に認識するわけではありません。文字の境界と、完全なメッセージの境界は別の問題です。
アプリケーションプロトコルは、固定長、長さフィールド、タイミング、特殊なマーカーなどを使ってメッセージを区切ることができます。それぞれに条件とトレードオフがあります。本記事では、シリアルフレーミングの簡単な例であるSLIPを用いて、マーカーとエスケープを説明します。すべてのシリアルプロトコルがSLIPを使用するという意味でも、既存のプロトコルを安易に変更すべきだという意味でもありません。
飛暢のFCT-1100-F1S1シングルポート3-in-1シリアルデバイスサーバーは、実際のシリアル・ネットワーク変換の例となります。インターフェースやネットワークを介して転送されるバイトに、新たな業務上の意味が自動的に付与されるわけではありません。本記事は、この製品の内部フレーミングプロトコルを推測するものではありません。実際の機能については、ドキュメントと設定を確認してください。
1つのマーカーが2つの役割を持つ理由
通信の両端で、特定のバイトを終端として使うことに合意しているとします。パーサーはそのバイトを受信すると、それまでにバッファーに蓄積したデータを渡します。この考え方は、文の終わりを示す句読点に似ています。しかし、バイナリデータにはどのようなバイト値も含まれ得るため、選んだ値がペイロードに含まれないとは限りません。
測定レコードに、終端マーカーと同じ値が含まれることがあります。パーサーは、その値をデータとして扱うべきでしょうか、それとも境界として扱うべきでしょうか。値だけでは、この2つを判別できません。送信側と受信側には、伝送路上で特殊な値の表現を変える共通ルールが必要です。
単に特定の値を禁止すると、元のデータで表現できる内容が制限され、測定値が気付かないうちに変わるおそれがあります。銅線を光ファイバーに置き換えても、この曖昧さは解消されません。光変換が変えるのは伝送媒体であり、アプリケーションプロトコルによる解釈ではないからです。リンク品質と符号化ルールは、別々に確認する必要があります。
エスケープが変えるのは表現であり、データではない
エスケープは、後続のバイトを合意済みのルールで解釈するための合図と考えることができます。送信側はペイロードを調べ、保護対象のバイト値を特殊なシーケンスに置き換えます。受信側はその逆変換を行い、元と同じ内容を復元できるはずです。
RFC 1055で説明されているSLIPの例では、16進値C0がEND、DBがESCです。ペイロード内のC0はDB DCに、ペイロード内のDBはDB DDになります。エスケープされていないC0が実際の終端境界を示します。これらの特定の値はこの例に固有のものであり、すべてのシリアルプロトコルに共通するものではありません。
なぜDBもエスケープするのでしょうか。DBは、次のバイトを特別に解釈するための導入バイトだからです。元のDBを区別せずに送信すると、次の通常の値がエスケープの後続バイトと誤認される可能性があります。区切り文字とエスケープ導入バイトの両方を保護することで、新たな曖昧さを防ぎます。

短い例で送信側から受信側までを追う
元のペイロードを11 C0 22 DB 33とします。この2つの特殊な値は、通常の内容としてフレーミング済みストリームに直接配置できません。符号化すると11 DB DC 22 DB DD 33になります。実際のENDマーカーでこの結果を区切ることで、受信側は制御上の役割と復元されたデータを区別できます。
この図では、パケットの前後にC0を配置しています。RFC 1055では、蓄積したノイズを排出する方法として、先頭でENDを送信することを説明しています。連続するマーカーによって生じる長さゼロの結果は、通常のIPパケットとして渡すべきではありません。他のプロトコルが、必ずしも両端に同一のマーカーを使うとは限りません。
復号後、ペイロード内のC0とDBは再び通常のデータになります。区切り文字自体は、渡される内容には含まれません。符号化により、伝送路上のバイト数が増えることがあります。シリアルサーバーのカウンター、キャプチャ、アプリケーション上の長さは、測定階層が異なれば一致しない場合がありますが、それだけでデータ損失が証明されるわけではありません。
受信側は現在の状態を保持する必要がある
パーサーは、各バイトを常に単独で判断できるわけではありません。少なくとも、通常の読み取り状態と、エスケープ導入バイトの後で後続バイトを待つ状態を区別する必要があります。通常状態ではENDがパケット境界を示します。DBを受信すると、直ちに元のデータとしてDBを出力するのではなく、後続バイトを待つ状態へ移行します。
待機状態では、受信側は合意済みの対応関係を適用して通常状態に戻ります。2つのバイトの関係はパーサーの状態によって維持されるため、両方のバイトがソフトウェアの同じ読み取り処理で届く必要はありません。ある読み取りがDBで終わり、次の読み取りがDCで始まる場合、受信側は状態を保持して変換を完了する必要があります。
実際の実装では、不正な後続バイト、バッファーの上限、空のパケット、中断に対するルールも必要です。本記事は、唯一の汎用的なエラー処理方針を規定するものではありません。ソフトウェアがネットワークの読み取りのたびに解析状態を消去したり、各読み取りを1つのメッセージと見なしたりすると、トランスポートがすべてのバイトを届けていてもフレーミングに失敗することがあります。

境界は誤り検査でもセキュリティ保証でもない
エスケープは表現上の曖昧さを解消します。それ自体で誤り検出、再送、認証、暗号化が追加されるわけではありません。ストリームをパケットに分割しても、各パケットが正しいことや、送信元が信頼できることの証明にはなりません。SLIP自体が提供する機能は限定的であり、汎用的な産業制御用セキュリティプロトコルとして扱うべきではありません。
プロトコルによって、検査とエスケープを適用する段階も異なる場合があります。PPPのHDLCに類似したフレーミングには、独自のフラグ、透過性、フレーム検査のルールがあり、その詳細はSLIPと同一ではありません。マーカー値、エスケープの後続バイト、検査段階を混同すると、両側でバイトは受信できても、どちらもパケットを受け付けられなくなることがあります。
元のアプリケーションデータ、符号化、物理伝送またはネットワーク伝送、復号、アプリケーションでの検証が、それぞれどこで行われるかを整理してください。エラーを調査するときは、期待される内容と比較する前に、観測している階層を特定してください。符号化された通信データと復号後のアプリケーションフィールドを直接バイト単位で比較すると、実際には存在しない障害があるように見えることがあります。
再現可能な少量のサンプルで共通ルールを確認する
まず、機器とプロトコルのドキュメントを確認してください。バージョン、インターフェース設定、パケット化の方法、キャプチャ箇所を記録します。通常のデータ、終端値を含むデータ、エスケープ値を含むデータ、特殊な値が連続するデータをテストしてください。符号化後と復号後の両方の形式を確認します。これらは方法を説明するための例であり、特定の製品を測定したという主張ではありません。
次に、実装上の対応が必要な場合は、分割された読み取り、複数のデータがまとめられた読み取り、接続の中断をテストしてください。許可された環境で無害なデータを使用し、例示したバイトを稼働中の本番環境へのコマンドとして使用しないでください。通信の両端で異なるプロトコルを使用している場合は、ボーレートを何度も変更する前に、どちらが変換を行うのかを確認してください。
階層の違いを意識してください。UARTは文字を識別し、フレーミングルールはメッセージを識別し、エスケープはペイロード内の特殊な値が制御マーカーと誤認されるのを防ぎます。これらを分けて考えることで、ポートがバイトを受信できても、アプリケーションが完全なメッセージを再構成できない理由を説明できます。
主な参考資料
RFC 1055:SLIP、1988年6月、インターネット標準ではありません; RFC 1662:HDLCに類似したフレーミングにおけるPPP、1994年7月。製品に関する参考情報: FCT-1100-F1S1シリアルデバイスサーバー;この製品がSLIPを使用していると主張するものではありません。
以下の中国語技術記事から翻訳: 中国語の原文記事を読む.
実務上のよくある質問
シリアル文字を受信すれば、パケットも自動的に識別されますか?
いいえ。UARTによる文字の受信とアプリケーションのフレーミングは別のものであり、通信の両端で同じフレーミングルールが必要です。
SLIPはペイロード内のC0とDBをどのようにエスケープしますか?
ペイロード内のC0はDB DCに、ペイロード内のDBはDB DDになります。エスケープされていないENDは境界を示します。他のプロトコルでは、異なるルールを使用する場合があります。
バイトエスケープは完全性検査や暗号化の代わりになりますか?
いいえ。制御マーカーとペイロード値の曖昧さを解消するものであり、それ自体で誤り検出、再送、認証、暗号化を提供するわけではありません。
適用範囲と参考資料
一般的なSLIPフレーミングの例であり、特定の製品や測定データに関する主張ではありません。


