2010-04-07 96 views
1

通過TCP共享COM端口到多個客戶端的簡單設計模式是什麼?通過TCP共享COM端口

例如,本地GPS設備可以實時向遠程主機傳輸座標。

所以我需要一個程序,將打開串口並接受像多個TCP連接:

class Program 
{ 
    public static void Main(string[] args) 
    { 
     SerialPort sp = new SerialPort("COM4", 19200, Parity.None, 8, StopBits.One); 

     Socket srv = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     srv.Bind(new IPEndPoint(IPAddress.Any, 8000)); 
     srv.Listen(20); 

     while (true) 
     { 
      Socket soc = srv.Accept(); 
      new Connection(soc); 
     } 
    } 
} 

然後,我會需要一個類來處理連接的客戶機之間的通信,使他們都可以看到數據並保持同步,以便客戶指令順序接收:

class Connection 
{ 
    static object lck = new object(); 
    static List<Connection> cons = new List<Connection>(); 

    public Socket socket; 
    public StreamReader reader; 
    public StreamWriter writer; 

    public Connection(Socket soc) 
    { 
     this.socket = soc; 
     this.reader = new StreamReader(new NetworkStream(soc, false)); 
     this.writer = new StreamWriter(new NetworkStream(soc, true)); 
     new Thread(ClientLoop).Start(); 
    } 

    void ClientLoop() 
    { 
     lock (lck) 
     { 
      connections.Add(this); 
     } 
     while (true) 
     { 
      lock (lck) 
      { 
       string line = reader.ReadLine(); 
       if (String.IsNullOrEmpty(line)) 
        break; 

       foreach (Connection con in cons) 
        con.writer.WriteLine(line); 
      } 
     } 
     lock (lck) 
     { 
      cons.Remove(this); 
      socket.Close(); 
     } 
    } 
} 

我奮力化解的問題是如何促進一個串口實例和線程之間的通信。

我不確定上面的代碼是否是最好的方式,所以有人有另一種解決方案(越簡單越好)?

回答

1

爲什麼在這樣的低級別(套接字)寫?爲什麼不使用WCF作爲客戶端和服務器之間的通信,並提供一個更清潔,強類型的接口,而不是原始訪問GPS設備?

像這樣的設備通常是獨立於客戶端呼入的最佳管理方式 - 也就是說,您有自己的單獨線程與GPS設備進行對話,以適當的時間間隔輪詢它並使用當前位置填充共享數據結構 - 客戶端進行服務調用並提供來自共享數據結構的數據。對於有時不可靠的設備連接,所有的錯誤處理和恢復都由GPS線程處理,客戶端不需要每個人都參與到這種混亂中。他們可以進行非阻塞呼叫以獲取狀態更新,而這些更新可能包含狀態「不可用」狀態,而GPS線程正在瘋狂嘗試重新建立通信。

因此,我會創建一個服務,抽象處理這個特定設備的細節,併爲客戶提供一個乾淨的接口。例如,它可能提供像GetPosition()這樣的服務,它返回一些像「GeoCoordinate」這樣的類。這樣,如果您需要支持其他位置感應設備,您可以添加它們而不需要對客戶端代碼進行任何更改。

    GPS <--Serial--> Server <--WCF--> Clients 

我有數百個不同的設備,在許多串行端口和其他半可靠的連接,這是我使用的方法的通信系統。見http://blog.abodit.com

-----按你使用TELNET附加要求:也許是這樣的:

創建處理與設備本身的所有通信的線程。

創建一個封裝單個WorkItem的類 - 要發送的內容,響應和WaitHandle。

使用隊列來排隊來自客戶端的請求。每個客戶端在WaitHandle上等待其響應準備就緒。

讓單個通信線程從該隊列中拉出工作項目,將它們發送到GPS設備,獲取響應,將響應存儲在WorkItem中(或設置失敗標誌),然後設置等待句柄WorkItem已完成。

如果請求速度超過GPS可處理的速度,請添加代碼,以便它可以返回緩存的值,用於在上次成功請求到設備的小時間窗口內發送請求。

實際上,您現在向所有客戶端展示了一個虛擬GPS設備,但在內部您將序列化其所有請求(在隊列中)並管理與單個線程上的GPS設備的通信,以便您可以執行請求 - 響應輕鬆循環而不受干擾。

這也允許您很好地(在等待句柄上)超時以通知客戶端當前沒有響應。

+0

感謝您使用WCF的建議。但是,我忽略了在我的問題中提到我想使用telnet客戶端進行連接,並且這將是雙向通信,而不僅僅是接收。 我很好奇看到您的實施,但我無法在您的博客上找到任何代碼 - 您是否有任何示例?我仍然喜歡在套接字級別工作,但是我在如何與不同線程溝通方面停滯不前。 – 2010-04-08 04:13:00

+0

博客上沒有代碼,對不起,這是一個龐大的系統。我會在我的答案中增加一些更多的建議。 – 2010-04-08 05:08:13

+0

感謝您的更新和體系結構建議 - 使用隊列是一種有效的解決方案。我還發現了以下鏈接,顯示如何將COM端口鏈接到單個TCP連接:http://www.javiervalcarce.eu/wiki/Access_to_serial_port_from_Internet – 2010-04-09 05:11:25