C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#串口监听与TCP转发

基于C#实现串口监听与TCP转发功能

作者:小码编匠

在工业自动化、物联网设备管理、远程监控等应用场景中,经常需要将本地串口设备的数据实时传输到远程服务器进行处理,本文将详细介绍如何使用 C# 创建一个串口监听服务,并将接收到的数据通过 TCP 协议转发至远程服务器,需要的朋友可以参考下

前言

在工业自动化、物联网设备管理、远程监控等应用场景中,经常需要将本地串口设备(如条码扫描枪、RFID读卡器、各类传感器)的数据实时传输到远程服务器进行处理。本文将详细介绍如何使用 C# 创建一个串口监听服务,并将接收到的数据通过 TCP 协议转发至远程服务器。

本方案实现的功能非常实用且简洁:当串口设备有数据输入时,程序自动捕获并将其转发至指定的 TCP 服务器。适用于远程数据采集、设备状态监控、嵌入式系统通信等多种场景。

一、实现原理

整个程序基于以下核心步骤构建:

1、创建串口监听服务:配置并打开串口,注册数据接收事件;

2、监听串口数据变化:通过 DataReceived 事件捕获新数据;

3、建立 TCP 连接:将接收到的数据通过 TCP 客户端发送到远程服务器;

4、实现重连机制:在网络异常中断后自动尝试重新连接;

5、资源释放与异常处理:确保程序退出或异常时能正确关闭串口和网络连接,避免资源泄漏。

二、代码实现

using System;
using System.IO.Ports;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

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}");
            }
        }
    }
}

三、功能详解

1、串口监听服务

使用 SerialPort 类实现串口监听,支持自定义配置如下:

示例配置:

_serialPort = new SerialPort
{
    PortName = _portName,
    BaudRate = _baudRate,
    DataBits = _dataBits,
    StopBits = _stopBits,
    Parity = _parity,
    ReadBufferSize = 4096,
    ReadTimeout = 500
};

2、数据变化检测与转发

通过注册 DataReceived 事件实现串口数据变化检测:

_serialPort.DataReceived += SerialPort_DataReceived;

当串口接收到数据后,事件处理程序自动触发:

1、读取缓冲区数据;

2、将其转换为字符串;

3、调用 SendDataToTcpServer 方法将数据转发到 TCP 服务器。

3、TCP 连接管理

使用 TcpClientNetworkStream 建立与服务器的连接,并实现以下功能:

4、错误处理与资源管理

四、应用场景

该解决方案适用于多种工业及物联网场景,包括但不限于:

1、工业自动化:PLC、传感器数据远程采集;

2、物联网设备管理:边缘设备数据集中上传;

3、零售系统:条码扫描枪数据实时上传;

4、医疗设备:仪器数据远程监控;

5、仓储物流:RFID 读写器数据同步。

五、配置说明

根据实际部署环境,需修改以下配置参数:

private static string _serverIp = "192.168.1.100";   // 服务器IP
private static int _serverPort = 8080;              // 服务器端口
private static string _portName = "COM1";           // 串口名称
private static int _baudRate = 9600;                // 波特率

总结

本文详细讲解了如何使用 C# 实现串口监听与 TCP 转发功能。该方案结构清晰、功能完整,具备良好的稳定性和可扩展性。你可以直接使用本示例作为基础模块,也可以根据具体业务需求进行定制开发。

对于需要远程采集串口设备数据的应用场景,该程序提供了一个轻量但高效的解决方案。无论是工业现场设备监控,还是物联网终端数据上传,都能从中受益。

以上就是基于C#实现串口监听与TCP转发功能的详细内容,更多关于C#串口监听与TCP转发的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文