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) に分割することをシミュレートしません。実際のイーサネット設定をシミュレートするには、これも行う必要があります。必要に応じてコメントで質問してください。クラスを延長する場合があります。