1

仮想デバイス (D) のセットがあります。デバイスは相互接続できます (物理接続を想定):

D1 -- D2

D2 -- D3

リンクごとに遅延が異なる可能性があります。

各デバイスには、データを生成できる一連の仮想サブデバイスが含まれています。サブデバイスは、論理接続に編成できます。サブデバイスは実際のバイト データを送信します。

私はC++、Qtを使用しています。シグナルスロットメカニズム QSignalMapper を使用しようとしましたが、良い解決策が見つかりませんでした。

明確な抽象化を構築するのを手伝ってください。どんなデザインパターンでも使用できますか?

4

1 に答える 1

1

Linkクラス間の物理リンクをシミュレートするクラスを定義する必要があります。最も興味深い質問は、デバイスを接続し、信号とスロットを使用して遅延をシミュレートする方法です。

私の提案は次のとおりです。send(QByteArray data)データを内部キューにエンキューし(ワイヤをシミュレート)、オプションのジッターを使用して特定のデフォルト遅延にタイムアウトを設定するスロットを実装します。次に、タイムアウトにより、キューからポップされたデータでシグナルが発生します。

デバイス間のルーターをシミュレートする場合は、再送信を行う必要があるため、キュー内のデータが多いほど遅延が大きくなることを考慮する必要があります。これをほぼシミュレートするには、現在のキューの長さに応じてタイムアウト値を設定できます。

これを手始めに:

class Link : public QObject
{
    Q_OBJECT

public:
    Link(Device *from, Device *to) :
        QObject(to), m_from(from), m_to(to)
    {
        //make my life dependant on both "from" and "to" objects
        connect(from, SIGNAL(destroyed()), SLOT(deleteLater()));

        //connect to the signals and slots of the devices
        connect(from, SIGNAL(send(QByteArray,Device*)),
                this, SLOT(  send(QByteArray,Device*)));
        connect(this, SIGNAL(receive(QByteArray,Device*,int)),
                to,   SLOT(  receive(QByteArray,Device*,int)));
    }

public slots:
    void send(QByteArray data, Device *receiver) {
        Message msg(data, 0, qobject_cast<Device*>(sender()), receiver);
        send(msg);
    }
    void send(Message msg) {
        msg.hops++; // here we increase the hops counter
        m_queue.enqueue(msg);
        QTimer::signalShot(m_delay, this, SLOT(timeout()));
    }

signals:
    void receive(QByteArray data, Device *sender, int hops);
    void forward(Message);

private slots:
    void timeout() {
        receive(m_queue.dequeue());
    }
    void receive(Message msg) {
        if(msg.receiver == m_to)
            // msg reached destination!
            emit receive(msg.data, msg.sender, msg.hops);
        else
            // forward to next link
            emit forward(msg);
    }

private:
    static const int m_delay = 100; // delay set to 100 ms
    QQueue<Message> m_queue;
    Device *m_from, *m_to;
};

タイプMessageは次のように定義されます。

struct Message {
    QByteArray data;
    int hops;
    Device *sender;
    Device *receiver;
    Message(data, hops, sender) : data(data), hops(hops),
                                  sender(sender), receiver(receiver) {}
};

次に、次のようにデバイスとリンクを作成します。

// Create devices:
Device *d1 = new Device(this);
Device *d2 = new Device(this);

// Create link:
Link *d1d2 = new Link(d1, d2);

または、転送ルールを使用した連鎖リンク:

// Create devices:
Device *d1 = new Device(this);
Device *d2 = new Device(this);
Device *d3 = new Device(this);

// Create links:
Link *l1 = new Link(d1, d2);
Link *l2 = new Link(d2, d3);

// Create forwarding rule:
connect(l1, SIGNAL(forward(Message)), l2, SLOT(send(Message)));

d1 によって送信されたすべてのデータ (シグナルが送信されたとき) は、100 ミリ秒の遅延で d2send(QByteArray)のスロットに転送されます。receive(QByteArray)データが d2 用でなかった場合、シグナルforward(Message)が送信され、別のリンクでキャッチする必要があります (転送ルールを参照)。その後、新しい着信メッセージとして扱われ、d3 に配信されます。

実際のネットワークはそのようには機能しないことに注意してください。このようなセットアップを完全にシミュレートするには、ルーティング戦略を実装する必要があります。これは非常に難しいことです。

また、このコードはテストしていないことに注意してください。;)

このアプローチは、データを小さなセグメント (それぞれ約 1.5 KB) に分割することをシミュレートしません。実際のイーサネット設定をシミュレートするには、これも行う必要があります。必要に応じてコメントで質問してください。クラスを延長する場合があります。

于 2012-05-22T11:23:58.073 に答える