2025-11-11
C#
00

目录

Industrial IoT Era: Are You Still Struggling with Legacy Serial Devices Unable to Connect to Networks?
🎯 Problem Analysis: Real Pain Points in Industrial Settings
Challenges of Traditional Serial Devices
Shortcomings of Existing Solutions
💡 Solution: Smart Converter Built with C#
Core Architecture Design
Technical Highlights
🔥 Code Implementation: Core Functionality Analysis
1. Main Form Class: System Control Center
2. Start Converter: One-Click Start of All Services
3. Data Processing Core: Efficient Queue Processing Mechanism
4. Client Management: Elegant Connection Handling
Running
🛠️ Real-world Application Scenarios
Factory Automation Integration
Remote Device Monitoring
⚡ Common Pitfalls and Solutions
1. Serial Port Occupation Issues
2. UI Thread Safety
3. Memory Leak Protection
🎯 Advanced Performance Optimization Tips
1. Data Buffer Optimization
2. Connection Pool Management
📊 Actual Test Results
💫 Summary and Outlook
🔑 Three Core Points:
🚀 Extension Directions:

Industrial IoT Era: Are You Still Struggling with Legacy Serial Devices Unable to Connect to Networks?

Are you still experiencing headaches because old serial devices can't directly access the network? Are you working late into the night due to complex protocol conversions? Today, I'll use a complete C# project to teach you step-by-step how to build a high-performance Serial-to-Ethernet converter, transforming traditional devices into smart terminals in seconds!

This is not just a simple conversion tool, but a complete industrial-grade solution featuring multi-client management, asynchronous data processing, real-time status monitoring, and other enterprise-level functions. Whether you're an embedded engineer or a .NET developer, this article will open up a new world of industrial connectivity for you!

🎯 Problem Analysis: Real Pain Points in Industrial Settings

Challenges of Traditional Serial Devices

In factory automation, numerous PLCs, sensors, instruments, and other devices still use RS232/RS485 serial communication. These devices face core problems:

  • Distance Limitations: Serial communication typically doesn't exceed 15 meters
  • Single Point Connection: One serial port can only connect to one device
  • Maintenance Difficulties: Complex wiring, time-consuming troubleshooting
  • Poor Scalability: Cannot directly connect to modern network systems

Shortcomings of Existing Solutions

While serial servers on the market can solve basic needs, they have obvious drawbacks:

  • High Costs: Industrial-grade products often cost thousands of dollars
  • Limited Functionality: Lack flexible data processing capabilities
  • Integration Difficulties: Hard to seamlessly integrate with existing systems

💡 Solution: Smart Converter Built with C#

Core Architecture Design

Our solution adopts a Producer-Consumer pattern, implementing efficient bidirectional data conversion through concurrent queues:

image.png

Technical Highlights

  • Asynchronous Non-blocking: Task-based asynchronous programming model
  • Thread Safety: Using ConcurrentQueue and SemaphoreSlim
  • Multi-client Support: Support multiple network devices connecting simultaneously
  • Real-time Monitoring: Complete status display and logging

🔥 Code Implementation: Core Functionality Analysis

1. Main Form Class: System Control Center

csharp
public partial class Form1 : Form { // Core components private SerialPort _serialPort; private TcpListener _tcpListener; private readonly List<ClientHandler> _connectedClients = new List<ClientHandler>(); // Thread safety mechanisms private readonly SemaphoreSlim _clientsSemaphore = new SemaphoreSlim(1, 1); private readonly ConcurrentQueue<byte[]> _serialDataQueue = new ConcurrentQueue<byte[]>(); private readonly ConcurrentQueue<byte[]> _networkDataQueue = new ConcurrentQueue<byte[]>(); // State management private CancellationTokenSource _cancellationTokenSource; private bool _isRunning = false; private long _totalBytesReceived = 0; private long _totalBytesSent = 0; }

💡 Design Highlights:

  • Using SemaphoreSlim ensures thread-safe access to the client list
  • ConcurrentQueue provides high-performance lock-free queue operations
  • Separated data queues implement bidirectional data flow management

2. Start Converter: One-Click Start of All Services

csharp
private async Task StartConverter() { // 🔧 Parameter validation if (string.IsNullOrEmpty(cmbSerialPorts.Text)) throw new InvalidOperationException("Please select a serial port"); if (!int.TryParse(txtTcpPort.Text, out int tcpPort) || tcpPort <= 0 || tcpPort > 65535) throw new InvalidOperationException("Please enter a valid TCP port (1-65535)"); // 🚀 Configure serial port _serialPort = new SerialPort { PortName = cmbSerialPorts.Text, BaudRate = int.Parse(cmbBaudRate.Text), DataBits = int.Parse(cmbDataBits.Text), Parity = (Parity)Enum.Parse(typeof(Parity), cmbParity.Text), StopBits = (StopBits)Enum.Parse(typeof(StopBits), cmbStopBits.Text), ReadTimeout = 500, WriteTimeout = 500 }; _serialPort.DataReceived += SerialPort_DataReceived; _serialPort.Open(); // 🌐 Start TCP listening _tcpListener = new TcpListener(IPAddress.Any, tcpPort); _tcpListener.Start(); _cancellationTokenSource = new CancellationTokenSource(); _isRunning = true; // 🔄 Start async tasks _ = Task.Run(() => AcceptClientsAsync(_cancellationTokenSource.Token)); _ = Task.Run(() => ProcessDataQueuesAsync(_cancellationTokenSource.Token)); LogMessage("Converter started", Color.Green); }

⚠️ Key Points to Remember:

  • Timeout settings prevent serial port blocking
  • Using Task.Run avoids blocking the UI thread
  • Event subscription must be completed before opening the serial port

3. Data Processing Core: Efficient Queue Processing Mechanism

csharp
private async Task ProcessDataQueuesAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { // 📤 Serial to network: broadcast to all clients while (_serialDataQueue.TryDequeue(out byte[] serialData)) { await BroadcastToClientsAsync(serialData); Interlocked.Add(ref _totalBytesSent, serialData.Length); } // 📥 Network to serial: write to serial device while (_networkDataQueue.TryDequeue(out byte[] networkData)) { if (_serialPort != null && _serialPort.IsOpen) { _serialPort.Write(networkData, 0, networkData.Length); Interlocked.Add(ref _totalBytesSent, networkData.Length); } } // ⏱️ Brief delay to avoid excessive CPU usage await Task.Delay(1, cancellationToken); } catch (Exception ex) { LogMessage($"Data processing error: {ex.Message}", Color.Red); await Task.Delay(100, cancellationToken); } } }

🎯 Performance Optimization Tips:

  • Using TryDequeue avoids blocking waits
  • Interlocked.Add ensures atomic counter operations
  • Appropriate delays balance CPU usage and response speed

4. Client Management: Elegant Connection Handling

csharp
private async Task BroadcastToClientsAsync(byte[] data) { List<ClientHandler> clientsToRemove = new List<ClientHandler>(); List<ClientHandler> currentClients; // 🔒 Get client list copy await _clientsSemaphore.WaitAsync(); try { currentClients = new List<ClientHandler>(_connectedClients); } finally { _clientsSemaphore.Release(); } // 🚀 Send data in parallel var sendTasks = new List<Task>(); foreach (var client in currentClients) { sendTasks.Add(SendToClientSafeAsync(client, data, clientsToRemove)); } await Task.WhenAll(sendTasks); // 🧹 Clean up disconnected clients if (clientsToRemove.Count > 0) { await _clientsSemaphore.WaitAsync(); try { foreach (var client in clientsToRemove) { _connectedClients.Remove(client); client.Dispose(); } } finally { _clientsSemaphore.Release(); } } }

💎 Design Essence:

  • Lock Separation Strategy: Copy the list first then release the lock, avoiding long-term occupation
  • Parallel Transmission: Using Task.WhenAll improves multi-client processing efficiency
  • Exception Isolation: Single client exceptions don't affect other connections

Running

image.png

image.png

🛠️ Real-world Application Scenarios

Factory Automation Integration

csharp
// Scenario: PLC data acquisition // PLC connects to converter via RS485, multiple host computers monitor production data simultaneously // Converter configuration: Baud rate 9600, Data bits 8, Stop bits 1, No parity

Remote Device Monitoring

csharp
// Scenario: Environmental monitoring stations // Temperature and humidity sensor data uploaded to cloud platform through converter // Support multiple monitoring centers receiving data simultaneously

⚡ Common Pitfalls and Solutions

1. Serial Port Occupation Issues

csharp
// ❌ Wrong: Improper resource release _serialPort.Close(); // Only closes, doesn't release // ✅ Correct: Complete resource release if (_serialPort != null && _serialPort.IsOpen) { _serialPort.DataReceived -= SerialPort_DataReceived; // Unsubscribe event _serialPort.Close(); _serialPort.Dispose(); // Release resources _serialPort = null; }

2. UI Thread Safety

csharp
// ❌ Wrong: Directly updating UI from worker thread lblStatus.Text = "Connected"; // May cause exceptions // ✅ Correct: Using Invoke mechanism if (InvokeRequired) { Invoke(new Action(() => lblStatus.Text = "Connected")); } else { lblStatus.Text = "Connected"; }

3. Memory Leak Protection

csharp
// ✅ Log length control to prevent memory overflow if (rtbLog.Lines.Length > 1000) { var lines = rtbLog.Lines.Skip(200).ToArray(); rtbLog.Lines = lines; }

🎯 Advanced Performance Optimization Tips

1. Data Buffer Optimization

csharp
// 💡 Batch processing improves efficiency private readonly List<byte[]> _batchBuffer = new List<byte[]>(); private const int BATCH_SIZE = 10; // Batch process data packets to reduce network IO operations if (_batchBuffer.Count >= BATCH_SIZE) { var combinedData = _batchBuffer.SelectMany(x => x).ToArray(); await BroadcastToClientsAsync(combinedData); _batchBuffer.Clear(); }

2. Connection Pool Management

csharp
// 💡 Client connection limitation private const int MAX_CLIENTS = 50; if (_connectedClients.Count >= MAX_CLIENTS) { LogMessage("Maximum connections reached, rejecting new connection", Color.Orange); newClient.Close(); return; }

📊 Actual Test Results

In actual deployment at an electronics manufacturing factory:

  • Device Count: 12 PLCs + 8 Frequency converters
  • Concurrent Connections: 25 monitoring terminals
  • Data Throughput: Average 2000 data packets per second
  • Stability: 30 days of continuous operation with zero failures
  • Response Latency: < 5ms (LAN environment)

💫 Summary and Outlook

Through this complete C# Serial-to-Ethernet project, we not only solved the practical problem of industrial device networking but also demonstrated the powerful capabilities of modern .NET technology in the industrial IoT field.

🔑 Three Core Points:

  1. Asynchronous programming patterns are the foundation for building high-performance network applications
  2. Thread-safe design determines system stability under high concurrency
  3. Resource management strategy affects application long-term operation quality

🚀 Extension Directions:

  • Add encrypted data transmission functionality
  • Integrate Modbus/Profinet and other industrial protocols
  • Support web management interface
  • Add data persistence storage

This solution has been validated in multiple industrial projects, saving over 60% in costs compared to commercial products. If you're developing similar projects, this complete code framework will save you significant development time.

What technical challenges have you encountered in industrial IoT projects? Welcome to share your practical experience in the comments, let's explore more optimization solutions together! If you find this article helpful, please share it with more engineering colleagues!


Follow me for more C# industrial application development insights!

相关信息

通过网盘分享的文件:AppSerialToEthernet.zip 链接: https://pan.baidu.com/s/1jYmkw1_sHaSwMFnXyvnLbQ?pwd=qwp4 提取码: qwp4 --来自百度网盘超级会员v9的分享

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!