2012-07-13 36 views
0

我正在使用TCP客戶機應用程序。我想分享我的問題,並想知道在應用程序中使用的數據包的更好的設計方案。對於Windows窗體應用程序的TCP數據包使用設計問題

目前我設計它爲: 消費者類,一旦它從套接字接收到數據包就會被激活。 PacketReceived事件一旦被識別並構建了有效的數據包,就被消費者類觸發。

現在: 我所有的形式(和用戶控制),這需要消耗包,已認購本次活動

得到通知,然後消耗通過檢查speficic封包ID興趣包。

這種設計不好的事情是,它需要編寫事件subscriptuion代碼和封包ID

驗證碼的各種形式(和用戶控制)。

有沒有更好的方法來完成工作,請建議。

我正在使用C#.net,Framework 3.5。

謝謝。 穆罕默德伊德利斯

回答

1

聽起來像你應該使用觀察者模式,而不是讓消費者決定哪個數據包發送到哪裏。

// implement this interface in all forms 
public interface IPacketSubscriber 
{ 
    void HandlePacket(Packet packet); 
} 

// like this 
public class SomeForm : Form, IPacketSubscriber 
{ 
    public SomeForm() 
    { 
     // subscribe in some way here. 
     YouSingleton.Consumer.Subscribe(1, this); 
     YouSingleton.Consumer.Subscribe(12, this); 
     YouSingleton.Consumer.Subscribe(25, this); 
    } 

    public void HandlePacket(Packet packet) 
    { 
     // got packet here 
    } 
} 

// Keeps track of all subscribers 
public class SubscriberList 
{ 
    Dictionary<int, List<IPacketSubscriber>> _subscribers 
     = new Dictionary<int, List<IPacketSubscriber>>(); 

    public void Subscribe(int packetId, IPacketSubscriber subscriber) 
    { 
     List<IPacketSubscriber> subscribers; 
     if (!_subscribers.TryGetValue(packetId, out subscribers)) 
     { 
      subscribers = new List<IPacketSubscriber>(); 
      _subscribers.Add(packetId, subscribers); 
     } 

     subscribers.Add(subscriber); 
    } 

    public void Publish(Packet packet) 
    { 
     List<IPacketSubscriber> subscribers; 
     if (!_subscribers.TryGetValue(packet.FunctionId, out subscribers)) 
     { 
      subscribers = new List<IPacketSubscriber>(); 
      _subscribers.Add(packet.FunctionId, subscribers); 
     } 

     foreach (var subscriber in subscribers) 
     { 
      subscriber.HandlePacket(packet); 
     } 
    } 

} 

// changes in the consumer class 
// composite pattern & law of demeter, do not expose the subscriberlist 
public class Consumer 
{ 
    SubscriberList _subscribers = new SubscriberList(); 

    public void Subscribe(int packetId, IPacketSubscriber subscriber) 
    { 
     if (subscriber == null) throw new ArgumentNullException("subscriber"); 
     _subscribers.Subscribe(packetId, subscriber); 
    } 

    protected void OnReceivedCompletePacket(Packet packet) 
    { 
     _subscribers.Publish(packet); 
    } 
} 

然而,您可以將事情分開多一點。表格並不需要知道消費者,只是他們可以從某個地方接收事件。讓我們用知識和創造另一個接口:

public interface IPacketDispatcher 
{ 
    void Subscribe(int packetId, IPacketSubscriber); 
} 

,然後簡單地改變,因此,這些表格使用的界面,而不是(取決於你如何暴露調度/消費者的形式)。

這個小小的改變使得它很容易測試你的表單並改變將來如何接收數據包。

相關問題