2012-08-25 35 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连接只是通过网络发送的字节流,您可以使用相同的模式从磁盘上的文件或串行端口读取二进制数据。