我正在开发一个简单的应用程序,它将通过TCP从硬件接收数据。 我在互联网上搜索了一些如何开发接收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 :(得分: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
}
}
答案 1 :(得分:1)
通常步骤相同:
1)从tcp流中读取数据并将其存储在缓冲区(通常是字节数组)中。
2)连续检查缓冲区(每次更新缓冲区)以确定是否到达完整的数据包。
3)解析缓冲区并将数据包提取到所需的OO对象
4)将对象添加到队列中以进一步处理或调用后台线程以使用数据包对象。
通过输出流发送数据的顺序几乎相同。
处理缓冲区时,事情会变得复杂/嘈杂/痛苦。您需要处理二进制数据以确定数据包何时结束而另一个数据包何时开始。当然这与您正在通信的设备的协议有关,如果它发送固定长度的数据包或开始/停止字节等... 此时没有标准解决方案,因为您要编写的代码取决于设备发送的数据。
编辑:您使用示例代码更新了您的问题,但是不重要的是记录的结构,该部分是简单且冗长的编写(如果您的结构有一个int
字段,您从中读取4个字节缓冲区并使用BitConverter
类在该字段上写入以将字节转换为int(例如)。您需要阅读硬件手册以检查它发送数据的格式(再次,开始/停止字节,固定长度等)。
这是非常抽象的,因为它针对每种情况,没有“烘焙解决方案”。此外,似乎你不明白如何流/ tcp连接/二进制数据包的工作原理,是什么让你认为这是tcp连接的问题,但事实并非如此。 Tcp连接只是通过网络发送的字节流,您可以使用相同的模式从磁盘上的文件或串行端口读取二进制数据。