2012-08-25 41 views
1

我正在開發一個簡單的應用程序,它將通過TCP從硬件接收數據。 我在網上搜索了一下如何開發一個程序來接收TCP數據,但還沒有找到任何我很滿意的東西。它或者是如何在C#中使用TCP的非常簡單的描述,或者是對高級框架的描述。通過C#中的TCP進行面向對象的通信#

我想要一個簡單的最佳實踐,即如何以良好的面向對象的方式組織我的程序的通信部分。有什麼建議麼?

理想情況下,我想這是通過TCP發送不同的結構存儲在相應的結構在程序

結構被髮送的內容:

Head 
{ 
    Int16 Mode; 
    Time  Start_time //(Unix time) 
    Int16 Number of records 
} 
for each record if mode == 1 
    char[20] Name_of_record 
for each record 
    float Value_of_record //(hardware-specific float) 
    Int16 Flag_of_record 
Foot 
{ 
    Time  Stop_time //(Unix time) 
} 

,這是每分鐘發送一次。 沒有開銷。它只是發出所有變量的值並且不再更多

編輯 我對服務器沒有任何控制權。

+0

IMHO,最廣泛使用的方法是[ WCF netTCPBinding](http://msdn.microsoft.com/en-us/library/ms731343.aspx)和[套接字](http://msdn.microsoft.com/en-us/ library/system.net.sockets.socket.aspx) – oleksii

+0

CodeProject上有一篇名爲「完整的TCP服務器/客戶端通信和C#中的RMI框架」的文章[這裏](http://www.codeproject.com/)文章/ 155282/A-Complete-TCP-Server-Client-Communication-and-RMI)和用法是[here](http://www.codeproject.com/Articles/153938/A-Complete-TCP-Server-Client - 通信 - 和 - RMI)。在所謂的「如何編寫可擴展的基於TCP/IP的服務器」中有一個很好的問題,就是[這裏](http://stackoverflow.com/q/869744/704144)。這些鏈接對您的問題沒有確切的答案,但它們可能對您的情況有用。 –

+0

但是這需要客戶端和服務器都使用這個框架? 我無法控制與之通信的硬件。該協議已經定義。 – magol

回答

2

我們可以使用異步通信接收TCP消息。

初始化服務器套接字,並嘗試連接:

// Specify the size according to your need. 
private byte[] bytData = new byte[1024 * 50000]; 
private Socket oServerSocket; 

private void WindowLoaded(object sender, RoutedEventArgs e) 
{ 
    try 
    { 
     // We are using TCP sockets 
     this.oServerSocket = new Socket(
     addressFamily: AddressFamily.InterNetwork, 
     socketType: SocketType.Stream, 
     protocolType: ProtocolType.Tcp); 

     // Assign the any IP of the hardware and listen on port number which the hardware is sending(here it's 5656) 
     var oIPEndPoint = new IPEndPoint(address: IPAddress.Any, port: 5656); 

     // Bind and listen on the given address 
     this.oServerSocket.Bind(localEP: oIPEndPoint); 
     this.oServerSocket.Listen(backlog: 4); 

     // Accept the incoming clients 
     this.oServerSocket.BeginAccept(this.OnAccept, null); 
     this.oLogger.WriteLog("Server started"); 
    } 
    catch (Exception ex) 
    { 
     // Handle Exception 
    } 
} 

在連接成功:

private void OnAccept(IAsyncResult ar) 
{ 
    try 
    { 
     var oClientSocket = this.oServerSocket.EndAccept(asyncResult: ar); 

     // Start listening for more clients 
     this.oServerSocket.BeginAccept(callback: this.OnAccept, state: null); 

     // Once the client connects then start receiving the commands from her 
     oClientSocket.BeginReceive(
     buffer: this.bytData, 
     offset: 0, 
     size: this.bytData.Length, 
     socketFlags: SocketFlags.None, 
     callback: this.OnReceive, 
     state: oClientSocket); 
    } 
    catch (Exception ex) 
    { 
     // Handle Exception 
    } 
} 

進程接收到的消息:

private void OnReceive(IAsyncResult ar) 
{ 
    try 
    { 
     var oClientSocket = (Socket)ar.AsyncState; 
     oClientSocket.EndReceive(asyncResult: ar); 

     /* Process the data here 

     BitConverter.ToInt32(value: this.bytData, startIndex: 0); 
     string SomeString= Encoding.ASCII.GetString(bytes: this.bytData, index: 8, count: 5); 

     */ 

     // Specify the size according to your need. 
     this.bytData = null; 
     this.bytData = new byte[1024 * 50000]; 
     oClientSocket.BeginReceive(
      buffer: this.bytData, 
      offset: 0, 
      size: this.bytData.Length, 
      socketFlags: SocketFlags.None, 
      callback: this.OnReceive, 
      state: oClientSocket); 
    } 

    catch (Exception ex) 
    { 
     // Handle Exception 
    } 
} 
+0

哇,@Ramesh寫了50%或更多的代碼:) – devundef

1

一般的步驟是相同的​​:

1)從TCP流中讀取的數據,並將其存儲在緩衝器中(通常是字節數組)。

2)連續檢查緩衝區(每次更新它時)以確定是否有完整的數據包到達。

3)解析在緩衝器和分組提取所需OO對象

4)對象添加到隊列中以進一步處理或調用後臺線程消耗包對象。

通過輸出流發送數據在逆序中幾乎是相同的。

處理緩衝區時,事情會變得複雜/嘈雜/痛苦。您需要處理二進制數據以確定數據包何時結束以及何時開始。當然,這與您正在通信的設備的協議有關,如果它發送固定長度的數據包或啓動/停止字節等等。 此時沒有標準解決方案,因爲您將編寫代碼取決於設備發送的數據。

編輯:您用示例代碼更新了您的問題,但不是重要的記錄結構,該部分是簡單和冗長的寫入(如果您的結構有一個int字段,您從緩衝區中讀取4個字節,例如使用BitConverter類將字節轉換爲int)。你需要閱讀硬件手冊來檢查它發送數據的格式(再次,開始/停止字節,固定長度等)。

這是非常抽象的,因爲它是特定於每種情況,沒有「烘焙解決方案」。此外,似乎你不明白如何流/ TCP連接/二進制數據包的作品,是什麼讓你認爲這是一個TCP連接的問題,但不是。 Tcp連接只是通過網絡發送的字節流,您可以使用相同的模式從磁盤上的文件或串行端口讀取二進制數據。