| C#/.NET Core Coding Guidelines | Entity-Framework | |
C#/.NET Communication & Protocols — Examples |
walk through a modular, real-world-ready example that touches on serial communication, TCP/IP sockets, and protocol parsing in C#.
public class SerialDriver
{
private SerialPort _port;
public void Initialize(string portName, int baudRate = 9600)
{
_port = new SerialPort(portName, baudRate)
{
Parity = Parity.None,
DataBits = 8,
StopBits = StopBits.One,
Handshake = Handshake.None,
ReadTimeout = 2000,
WriteTimeout = 2000
};
_port.DataReceived += OnDataReceived;
_port.Open();
}
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = _port.ReadLine();
ParseProtocol(data);
}
public void Send(string message)
{
if (_port?.IsOpen == true)
_port.WriteLine(message);
}
private void ParseProtocol(string raw)
{
// Example: parse a simple key-value protocol
var parts = raw.Split('=');
if (parts.Length == 2)
Console.WriteLine($"Key: {parts[0]}, Value: {parts[1]}");
}
}
Note: Need to install Nuget Package System.IO.Ports
using System.Net.Sockets;
using System.Text;
public class TcpClientDriver
{
private TcpClient _client;
private NetworkStream _stream;
public void Connect(string ip, int port)
{
_client = new TcpClient(ip, port);
_stream = _client.GetStream();
}
public void Send(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
_stream.Write(data, 0, data.Length);
}
public void Receive()
{
byte[] buffer = new byte[1024];
int bytes = _stream.Read(buffer, 0, buffer.Length);
string response = Encoding.UTF8.GetString(buffer, 0, bytes);
ParseProtocol(response);
}
private void ParseProtocol(string raw)
{
// Reuse same parser logic or extend for TCP framing
Console.WriteLine($"Received: {raw}");
}
}
For scalable driver development:
IProtocolParser interface and inject parsers via DI for testability and extensibility.
public interface IProtocolParser
{
bool TryParse(string raw, out ParsedMessage result);
}
Cause: Assuming fixed-length messages or failing to detect start/end markers.
Impact: Misaligned reads, partial messages, or buffer overflows.
Fix: Use framing strategies like STX/ETX markers, length-prefixed headers, or newline delimiters.
Cause: Mixing UTF-8, ASCII, or binary without explicit handling.
Impact: Garbled data, failed deserialization, or silent corruption.
Fix: Normalize encoding at the transport layer and validate before parsing.
Cause: Ignoring handshake states, session tokens, or expected transitions.
Impact: Invalid command execution, security holes, or dropped connections.
Fix: Implement a finite state machine (FSM) to track protocol phases.
Cause: No schema validation or loose parsing logic.
Impact: Crashes, undefined behavior, or security vulnerabilities.
Fix: Use strict parsers with schema enforcement (e.g., JSON schema, XML XSD, or custom validators).
Cause: Reading too much or too little from the stream.
Impact: Data truncation, overflow, or deadlocks.
Fix: Always check buffer bounds and use circular buffers or stream parsers for continuous data.
Cause: Protocol changes without backward compatibility.
Impact: Legacy clients fail, or newer features break older parsers.
Fix: Embed version headers and use strategy patterns for parser dispatch.
Cause: Parsing shared buffers across threads without locks.
Impact: Data corruption or inconsistent state.
Fix: Use thread-safe queues or async pipelines with proper synchronization.
Cause: Swallowing exceptions or ignoring parse errors.
Impact: Undetected bugs, data loss, or security risks.
Fix: Log all parse failures with context and metrics. Use structured logging.
| C#/.NET Core Coding Guidelines | Entity-Framework | |