2012-05-21 3 views
1

У меня есть набор виртуальных устройств (D). Устройства могут быть перекрестно соединены (предположим, физическое соединение):Схема проектирования для обмена данными

D1 - D2

D2 - D3

Каждое звено, возможно, будет иметь различную задержку.

Каждое устройство содержит набор виртуальных под-устройств (устройств), которые могут генерировать некоторые данные. Под-устройства могут быть организованы в логические соединения. Под-устройства передают реальные байтовые данные.

Я использую C++, Qt. Я попытался использовать механизм сигнального слота, QSignalMapper, но я не нашел хорошего решения.

Пожалуйста, помогите мне построить четкую абстракцию. Могу ли я использовать любой шаблон дизайна?

+0

У вас есть виртуальные устройства, которые физически связаны и имеют задержку? Вы имитируете сеть или какие именно устройства? – leemes

+0

Я имитирую сеть. – legotron

+0

Непонятно, какое именно «соединение» или «связь» вы ищете между виртуальными устройствами. Нужно ли им просто называть методы друг на друга? Кроме того, какую роль играют под-устройства? – Brady

ответ

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 (когда он испускает сигнал send(QByteArray)) передается с задержкой в ​​100 мс в слот receive(QByteArray) от d2. Если данные не были для d2, сигнал forward(Message) испускается, что должно быть уловлено другой ссылкой (см. Правило пересылки). Затем он обрабатывается как новое входящее сообщение и отправляется на d3.

Обратите внимание, что настоящие сети не работают так. Вам нужно будет реализовать стратегии маршрутизации, чтобы полностью имитировать такую ​​настройку; что довольно сложно.

Также обратите внимание, что я не тестировал этот код. ;)

Этот подход не моделирует разделение данных на небольшие сегменты (от 1,5 КБ каждый). Чтобы смоделировать реальную настройку Ethernet, вам также нужно будет это сделать. Спросите в комментариях, если вам нужно, и я могу расширить класс.

+0

Ницца, это хорошая стартовая точка. Класс Link очень прост. Но если у меня будет дерево устройств, могу ли я подключить Link к цепочкам? Как я могу отправлять данные по нескольким ссылкам, чтобы получатель знал, кто был первым отправителем? Может быть, нам нужно создать класс сообщений, который перемещается по ссылкам, подсчитывает хмель, маркирует переданные устройства и т. Д. – legotron

+0

@legotron Да, это тоже возможно. Я обновляю класс. – leemes

+0

@legotron см. Мой обновленный ответ. Как вы можете видеть, теперь это осложняется;) – leemes

Смежные вопросы