C#实现TCP客户端管理:支持SCPI指令的发送与接收
引言
在工业自动化、仪器控制和测试测量领域,SCPI(Standard Commands for Programmable Instruments)是一种广泛使用的标准命令语言。本文将介绍如何使用C#实现一个TCP客户端管理类,专门用于与非16进制数据格式的TCP服务端通信,特别适合处理SCPI指令的发送和接收。
核心类设计
1. TcpMultiClientManager类
TcpMultiClientManager
是一个管理多个TCP客户端连接的高级封装类,主要功能包括:
public class TcpMultiClientManager : IDisposable
{
private readonly List<(string Ip, int Port)> _clientConfigurations;
private readonly ConcurrentDictionary<(string Ip, int Port), TcpCommunication> _clients;
private readonly ConcurrentDictionary<(string Ip, int Port), (bool IsOn, string Current, string Voltage)> _deviceStatus;
// ... 其他成员和方法
}
主要特点:
- 支持管理多个TCP客户端连接
- 线程安全的并发集合存储客户端和设备状态
- 异步连接和消息接收
- 设备状态监控和管理
2. TcpCommunication类
TcpCommunication
是实际的TCP通信实现类,封装了底层TCP操作:
public class TcpCommunication : IDisposable
{
private readonly string _ip;
private readonly int _port;
private TcpClient _tcpClient;
private NetworkStream _networkStream;
// ... 其他成员和方法
}
主要特点:
- 封装TCP连接和流操作
- 支持同步和异步通信
- 提供SCPI指令发送和响应接收功能
- 完善的错误处理和日志记录
核心功能实现
1. 初始化连接
public async Task InitializeAsync()
{
var tasks = new List<Task>();
foreach (var (ip, port) in _clientConfigurations)
{
tasks.Add(Task.Run(async () =>
{
var client = new TcpCommunication(ip, port);
if (_clients.TryAdd((ip, port), client))
{
await ConnectClient(ip, port);
await StartReceivingMessages(ip, port);
}
}));
}
await Task.WhenAll(tasks);
}
2. SCPI指令发送与接收
同步方式:
public string SendAndSendCommand(string ip, int port, string command)
{
if (_clients.TryGetValue((ip, port), out var client))
{
return client.TestSendCommandAndGetResponse(command);
}
else
{
logWriter.WriteLogMessage(ip + port + "TestDeviceStatus函数未找到指定的服务端!");
return "0.0";
}
}
异步方式:
public async Task SendCommandAsync(string command)
{
if (!IsConnected)
{
Console.WriteLine("设备未连接");
logWriter.WriteLogMessage("同步接收数据设备未连接");
}
try
{
byte[] buffer = Encoding.ASCII.GetBytes(command);
await _networkStream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
Console.WriteLine($"Error sending command: {
ex.Message}");
Disconnect();
throw;
}
}
3. 设备状态监控
public void TestDeviceStatus(string ip, int port)
{
try
{
bool isOn = false;
string CURR = SendAndSendCommand(ip, port, "MEAS:CURR?");
string VOLT = SendAndSendCommand(ip, port, "MEAS:VOLT?");
// 数据处理逻辑
if (voltage > 5)
{
isOn = true;
}
_deviceStatus.AddOrUpdate(
(ip, port),
(isOn, CURR, VOLT),
(key, oldValue) => (isOn, CURR, VOLT)
);
}
catch (Exception ex)
{
// 错误处理
}
}
使用示例
1. 初始化并连接多个设备
var configurations = new List<(string, int)>
{
("192.168.1.100", 5025),
("192.168.1.101", 5025),
("192.168.1.102", 5025)
};
var manager = new TcpMultiClientManager(configurations);
await manager.InitializeAsync();
2. 发送SCPI指令并获取响应
// 同步方式
string current = manager.SendAndSendCommand("192.168.1.100", 5025, "MEAS:CURR?");
Console.WriteLine($"Current: {
current}");
// 异步方式
await manager.SendCommandToClient("192.168.1.100", 5025, "OUTP ON");
3. 监控设备状态
manager.TestDeviceStatus("192.168.1.100", 5025);
var status = manager.GetAllDeviceStatus();
foreach (var s in status)
{
Console.WriteLine($"IP: {
s.Ip}, Port: {
s.Port}, IsOn: {
s.IsOn}, Current: {
s.Current}, Voltage: {
s.Voltage}");
}
TcpCommunication 类完整代码:
public class TcpCommunication : IDisposable
{
public string Ip => _ip;
private readonly string _ip;
private readonly int _port;
private TcpClient _tcpClient;
pr