2012-05-21 60 views
1

我有一組虛擬設備(D)。 設備可以是交叉連接(假定,物理連接):數據交換的設計模式

D1 - D2

D2 - D3

每個鏈接可能將具有不同的等待時間。

每個設備包含一組可以生成一些數據的虛擬子設備。 子設備可以組織爲邏輯連接。 子設備將傳輸實際的字節數據。

我使用C++,Qt。 我試過使用信號槽機制QSignalMapper,但是我沒有找到好的解決方案。

請幫助我建立明確的抽象。 我可以使用任何設計模式嗎?

+0

你有物理連接並有延遲的虛擬設備?你在模擬一個網絡還是這些設備? – leemes

+0

我在模擬網絡。 – legotron

+0

其實並不清楚你在虛擬設備之間尋找什麼樣的'connection'或'link'。他們只需要能夠相互調用方法?另外,子設備扮演什麼角色? – 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毫秒到槽d2的receive(QByteArray)的延遲轉移。如果數據不是用於d2的,則信號forward(Message)被髮射,這必須被另一個鏈路捕獲(參見轉發規則)。然後它會被視爲新的傳入消息並傳遞給d3。

請注意,真實的網絡不會像那樣工作。您需要實施路由策略以完全模擬此類設置;這是相當困難的。

另請注意,我沒有測試此代碼。 ;)

此方法不模擬將數據拆分爲小段(每段大小爲1.5 KB)。要模擬真實的以太網設置,您也需要這樣做。如果需要,請在評論中提問,我可以延長課程。

+0

不錯,這是一個很好的起點。你的鏈接類非常清晰。但是如果我將有一個設備樹,我可以連接Link的鏈?我如何通過多個鏈接發送數據,以便收件人知道誰是第一個發件人?可能是我們需要創建消息類,它通過鏈接傳播,計算跳數,標記Device的傳遞等。 – legotron

+0

@legotron是的,這也是可能的。我更新課程。 – leemes

+0

@legotron看到我更新的答案。正如你所看到的,現在變得複雜了;) – leemes