Вы должны определить класс 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 (когда он испускает сигнал send(QByteArray)
) передается с задержкой в 100 мс в слот receive(QByteArray)
от d2. Если данные не были для d2, сигнал forward(Message)
испускается, что должно быть уловлено другой ссылкой (см. Правило пересылки). Затем он обрабатывается как новое входящее сообщение и отправляется на d3.
Обратите внимание, что настоящие сети не работают так. Вам нужно будет реализовать стратегии маршрутизации, чтобы полностью имитировать такую настройку; что довольно сложно.
Также обратите внимание, что я не тестировал этот код. ;)
Этот подход не моделирует разделение данных на небольшие сегменты (от 1,5 КБ каждый). Чтобы смоделировать реальную настройку Ethernet, вам также нужно будет это сделать. Спросите в комментариях, если вам нужно, и я могу расширить класс.
У вас есть виртуальные устройства, которые физически связаны и имеют задержку? Вы имитируете сеть или какие именно устройства? – leemes
Я имитирую сеть. – legotron
Непонятно, какое именно «соединение» или «связь» вы ищете между виртуальными устройствами. Нужно ли им просто называть методы друг на друга? Кроме того, какую роль играют под-устройства? – Brady