本文详细介绍如何使用C#创建串口监听服务,并将数据变化实时通过TCP转发到服务器。包含完整代码示例与实现思路,适合需要远程数据采集、工业设备监控的开发者参考。
在工业自动化、物联网设备管理、远程监控等应用场景中,经常需要将本地串口设备(如条码扫描枪、RFID读卡器、各类传感器)的数据实时传输到远程服务器进行处理。本文将详细讲解如何使用C#实现串口数据监听与TCP转发功能。
我们的实现基于以下核心步骤:
下面是完整的C#代码实现,包含详细的中文注释:
C#using System.IO.Ports;
using System.Net.Sockets;
using System.Text;
namespace AppComTransTcp
{
internal class Program
{
// TCP客户端
private static TcpClient _tcpClient;
// 网络数据流
private static NetworkStream _networkStream;
// 串口对象
private static SerialPort _serialPort;
// TCP服务器IP地址
private static string _serverIp = "127.0.0.1";
// TCP服务器端口
private static int _serverPort = 3001;
// 串口名称
private static string _portName = "COM1";
// 波特率
private static int _baudRate = 9600;
// 数据位
private static int _dataBits = 8;
// 停止位
private static StopBits _stopBits = StopBits.One;
// 校验位
private static Parity _parity = Parity.None;
// 重连间隔(毫秒)
private static int _reconnectInterval = 5000;
// 是否继续运行
private static bool _isRunning = true;
static void Main(string[] args)
{
Console.WriteLine("串口TCP转发服务启动中...");
// 初始化并启动服务
InitializeService();
Console.WriteLine("服务已启动。按 'q' 退出程序。");
// 保持程序运行,直到用户输入q退出
while (_isRunning)
{
var key = Console.ReadKey(true);
if (key.KeyChar == 'q' || key.KeyChar == 'Q')
{
_isRunning = false;
}
}
// 关闭资源
CloseConnections();
Console.WriteLine("程序已退出。");
}
/// <summary>
/// 初始化服务,包括串口和TCP连接
/// </summary>
private static void InitializeService()
{
try
{
// 初始化串口
InitializeSerialPort();
// 初始化TCP连接
ConnectToTcpServer();
// 启动重连检查任务
StartReconnectionTask();
}
catch (Exception ex)
{
Console.WriteLine($"初始化服务失败: {ex.Message}");
}
}
/// <summary>
/// 初始化串口设置
/// </summary>
private static void InitializeSerialPort()
{
try
{
// 创建并配置串口对象
_serialPort = new SerialPort
{
PortName = _portName,
BaudRate = _baudRate,
DataBits = _dataBits,
StopBits = _stopBits,
Parity = _parity,
// 设置读缓冲区大小
ReadBufferSize = 4096,
// 设置读超时
ReadTimeout = 500
};
// 注册数据接收事件
_serialPort.DataReceived += SerialPort_DataReceived;
// 打开串口
_serialPort.Open();
Console.WriteLine($"串口 {_portName} 已成功打开,波特率: {_baudRate}");
}
catch (Exception ex)
{
Console.WriteLine($"初始化串口失败: {ex.Message}");
throw;
}
}
/// <summary>
/// 建立TCP服务器连接
/// </summary>
private static void ConnectToTcpServer()
{
try
{
// 创建TCP客户端并连接服务器
_tcpClient = new TcpClient();
_tcpClient.Connect(_serverIp, _serverPort);
_networkStream = _tcpClient.GetStream();
Console.WriteLine($"已成功连接到TCP服务器 {_serverIp}:{_serverPort}");
}
catch (Exception ex)
{
Console.WriteLine($"连接TCP服务器失败: {ex.Message}");
// 这里不抛出异常,让重连机制处理
}
}
/// <summary>
/// 启动TCP重连检查任务
/// </summary>
private static void StartReconnectionTask()
{
Task.Run(async () =>
{
while (_isRunning)
{
try
{
// 检查TCP连接状态
if (_tcpClient == null || !_tcpClient.Connected)
{
Console.WriteLine("TCP连接已断开,尝试重新连接...");
// 关闭旧连接
if (_tcpClient != null)
{
_tcpClient.Close();
_tcpClient.Dispose();
}
// 创建新连接
ConnectToTcpServer();
}
}
catch (Exception ex)
{
Console.WriteLine($"重连过程发生错误: {ex.Message}");
}
// 等待指定时间后再次检查
await Task.Delay(_reconnectInterval);
}
});
}
/// <summary>
/// 串口数据接收事件处理
/// </summary>
private static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
// 确保有足够的数据可读
if (_serialPort.BytesToRead <= 0)
return;
// 读取串口数据
byte[] buffer = new byte[_serialPort.BytesToRead];
_serialPort.Read(buffer, 0, buffer.Length);
// 转换为字符串(可根据实际需求修改编码方式)
string data = Encoding.UTF8.GetString(buffer);
Console.WriteLine($"接收到串口数据: {data}");
// 将数据转发到TCP服务器
SendDataToTcpServer(buffer);
}
catch (Exception ex)
{
Console.WriteLine($"处理串口数据时发生错误: {ex.Message}");
}
}
/// <summary>
/// 发送数据到TCP服务器
/// </summary>
private static void SendDataToTcpServer(byte[] data)
{
try
{
// 检查TCP连接是否可用
if (_tcpClient != null && _tcpClient.Connected && _networkStream != null)
{
// 发送数据
_networkStream.Write(data, 0, data.Length);
_networkStream.Flush();
Console.WriteLine($"已发送 {data.Length} 字节数据到TCP服务器");
}
else
{
Console.WriteLine("TCP连接不可用,数据发送失败");
}
}
catch (Exception ex)
{
Console.WriteLine($"发送数据到TCP服务器失败: {ex.Message}");
// 标记连接为断开,让重连机制处理
if (_tcpClient != null)
{
_tcpClient.Close();
}
}
}
/// <summary>
/// 关闭所有连接并释放资源
/// </summary>
private static void CloseConnections()
{
try
{
// 关闭串口
if (_serialPort != null && _serialPort.IsOpen)
{
_serialPort.DataReceived -= SerialPort_DataReceived;
_serialPort.Close();
_serialPort.Dispose();
Console.WriteLine("串口已关闭");
}
// 关闭TCP连接
if (_networkStream != null)
{
_networkStream.Close();
_networkStream.Dispose();
}
if (_tcpClient != null)
{
_tcpClient.Close();
_tcpClient.Dispose();
Console.WriteLine("TCP连接已关闭");
}
}
catch (Exception ex)
{
Console.WriteLine($"关闭连接时发生错误: {ex.Message}");
}
}
}
}
程序通过SerialPort
类实现串口监听,主要参数包括:
C#_serialPort = new SerialPort
{
PortName = _portName,
BaudRate = _baudRate,
DataBits = _dataBits,
StopBits = _stopBits,
Parity = _parity,
ReadBufferSize = 4096,
ReadTimeout = 500
};
通过注册DataReceived
事件实现串口数据变化检测:
C#_serialPort.DataReceived += SerialPort_DataReceived;
当串口接收到数据后,事件处理程序自动触发:
SendDataToTcpServer
方法将数据转发到TCP服务器程序使用TcpClient
类建立与TCP服务器的连接:
程序实现全面的错误处理机制:
本解决方案适用于多种实际应用场景:
实际使用时,您需要根据需求修改以下配置:
C#// TCP服务器IP地址
private static string _serverIp = "192.168.1.100";
// TCP服务器端口
private static int _serverPort = 8080;
// 串口名称
private static string _portName = "COM1";
// 波特率
private static int _baudRate = 9600;
本文详细介绍了如何使用C#实现串口数据监听和TCP转发功能。通过合理的架构设计和完善的错误处理,该解决方案可以稳定可靠地工作在各种环境中。代码示例提供了完整的实现,您可以直接参考使用,也可以根据自己的需求进行定制和扩展。
对于需要将现场设备数据远程传输的场景,本文提供的解决方案可以作为基础框架,帮助您快速构建自己的数据采集和转发系统。
关键词:C#串口通信、TCP数据转发、SerialPort编程、C#网络编程、串口监听服务、工业数据采集、C#物联网开发
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!