15

ソフトウェアに独自の通信プロトコル スタックを実装しようとしていますが、どこから始めればよいかわかりません。これは私がこれまでに行ったことのない種類の作業であり、最良の/推奨されるアプローチについてリソースの面で助けを求めています.

私は c/c++ を使用し、ライブラリ (BSD/BOOST/Apache) を自由に使用できますが、GPL は使用しません。私は C++ を広範囲に使用してきたので、C++ の機能を使用することは問題ではありません。

プロトコル スタックには 3 つのレイヤーがあり、すでに完全に仕様が規定され、正式に検証されています。したがって、私がする必要があるのは、指定された言語で実装して完全にテストすることだけです。また、プロトコルは非常に単純ですが、信頼できる物理トランスポート層を介してさまざまなデバイスで実行できることにも言及する必要があります。イベント、入力、出力、副作用、およびプロトコル ステート マシンの動作を理解しています。通常、物理層から受信したメッセージを読み取るために割り込みを受け取り、それを読み取って待ち受けデバイスに送信します。受信デバイスは、応答メッセージを処理してプロトコル層に渡し、物理層に送信できます。

参照/推奨事項の助けをいただければ幸いです。それらを実装する方法を理解するのに役立つだけであれば、別の言語を使用しても構わないと思っていますが、最終的には選択した言語に頼る必要があります。

更新:実装したいプロトコルの例はSNEPのようなものです。

接続管理について心配する必要はありません。接続はすでに確立されており、プロトコルが行うのは、仕様でプロトコル メッセージがすでに明確に定義されているデータ交換であると想定できます。

4

3 に答える 3

11

インターフェイスとメッセージから始めます。

ピアがメッセージを交換できるようにするセッションのインターフェースを宣言します。メッセージを、int、double、std::string、および std::vector などの単純な型を持つ C++ 構造体として宣言します。例えば:

// these are your protocol messages
struct HelloRequest {
    uint32_t seq_no;
    // more stuff
};
struct HelloResponse {
    uint32_t seq_no;
    // more stuff
};

// Session callback for received messages
struct SessionReceiver {
    virtual void connected(Session*) = 0;
    virtual void receive(Session* from, HelloRequest msg) = 0;
    virtual void receive(Session* from, HelloResponse msg) = 0;
    virtual void disconnected(Session*) = 0;
};

// Session interface to send messages
struct Session {
    virtual void send(HelloRequest msg) = 0;
    virtual void send(HelloResponse msg) = 0;
};

// this connects asynchronously and then calls SessionReceiver::connected() with a newly established session
struct SessionInitiator {
    virtual void connect(SessionReceiver* cb, std::string peer) = 0;
};

// this accepts connections asynchronously and then calls SessionReceiver::connected() with a newly accepted session
struct SessionAcceptor {
    virtual void listen(SessionReceiver* cb, std::string port) = 0;
};

次に、これらのインターフェースを使用するビジネス ロジックをコーディングして、インターフェースをテストします。インターフェイスで必要なロジックを実装できると確信したら、libevent や Boost.Asio などの好みのイベント駆動型フレームワークを使用して、インターフェイスとメッセージのシリアル化を実装します。

編集: インターフェイスを使用すると、モックまたはテストの実装を使用できることに注意してください。また、シリアル化がインターフェイスの背後で行われるという事実は、インプロセス ピアの場合、メッセージをシリアル化および逆シリアル化する必要がなく、メッセージをそのまま渡すことができることを意味します。

于 2011-02-04T15:26:49.260 に答える
5

Boost.ASIOは、C++ での非同期 (または同期) ネットワーク通信に関してはかなり最先端です。

于 2011-02-04T15:24:51.110 に答える
5

Google Protocol Buffersをご覧ください。

説明から:

プロトコル バッファは、構造化データをシリアル化するための柔軟で効率的な自動化されたメカニズムです。XML を考えてみてください。データをどのように構造化するかを一度定義すると、特別に生成されたソース コードを使用して、さまざまなデータ ストリームとの間で、さまざまな言語を使用して構造化データを簡単に読み書きできます。「古い」形式に対してコンパイルされた展開済みプログラムを壊すことなく、データ構造を更新することもできます。

Protocol Buffers は言語とプラットフォームに依存しないため、プロジェクトに適合するはずです。ライセンスは見つかりませんでしたが、少なくともどこにも「GPL」とは書かれていませんでした。

これは、プロトコルに役立ちます。実際のデータ転送では、OS を自分で作成する場合を除き、使用する必要のあるプリミティブがいくつかあるはずです。もう少し詳細を提供しない限り、実装に関するより正確なヘルプを提供することは困難です。たとえば、どの通信チャネルを使用していますか? イーサネット?

ただし、経験則として、ISR はできるだけ短くする必要があります。これらの種類のソリューションでは、通常、データをリング バッファーにコピーすることを意味します。これにより、ISR にメモリを割り当てる必要がなくなります。ISR は、データをコピーした後、パッケージの上位レイヤーに通知する必要があります。DMA を使用できる場合は、それを使用します。その場合、DMA 転送を開始する前に通知を送信できる可能性があります。

Linux Device Drivers、特に第 10 章もチェックしてください。下半分と上半分についての部分をチェックしてください。

于 2011-02-04T17:57:44.710 に答える