当前位置: 首页 > news >正文

C#通讯关键类的API

12 个 C# 通讯核心类的完整 API 解析、实用细节及场景化示例,涵盖串口、Modbus、TCP/UDP、域名解析等场景,补充此前未覆盖的关键属性 / 方法(如Dns域名解析、SerialPort硬件控制),并强化实际开发中的易错点说明。

1. SerialPort(串口通信)

命名空间System.IO.Ports

核心功能:控制 RS-232/RS-485 串口设备,支持参数配置、数据收发,是硬件交互(如传感器、PLC)的核心类。

关键 API(含补充硬件控制)

类别名称及说明
基础配置PortName:串口名(如 "COM3",需通过SerialPort.GetPortNames()获取系统可用串口)BaudRate:波特率(常见 9600/115200,需与设备一致)Parity:校验位(None/Odd/Even,无校验最常用)DataBits:数据位(固定 8 位,硬件标准)StopBits:停止位(One/Two,1 位最常用)
硬件控制DtrEnable:是否启用 DTR(数据终端就绪)信号(部分设备需置true才能通信)RtsEnable:是否启用 RTS(请求发送)信号(硬件流控必设)Handshake:流控方式(None/XOnXOff软件流控 /RequestToSend硬件流控)
数据操作Open()/Close():打开 / 关闭串口(需用try-catch捕获占用 / 不存在异常)Write(byte[] buffer, int offset, int count):发送字节数组Read(byte[] buffer, int offset, int count):读取指定长度字节ReadLine():读取一行(直到NewLine,适合文本协议)DataReceived:数据接收事件(注意:事件在子线程触发,跨 UI 需 Invoke
缓存与超时BytesToRead:接收缓冲区待读字节数DiscardInBuffer()/DiscardOutBuffer():清空接收 / 发送缓存ReadTimeout/WriteTimeout:读写超时(毫秒,超时抛TimeoutException

示例(带硬件流控的 PLC 串口通信)

using System;
using System.IO.Ports;
using System.Windows.Forms; // 若需UI交互
​
class PlcSerialComm
{private SerialPort _plcPort;private TextBox _logTextBox; // UI文本框(用于显示日志)
​public PlcSerialComm(TextBox logTextBox){_logTextBox = logTextBox;_plcPort = new SerialPort{PortName = "COM4",BaudRate = 115200,Parity = Parity.Even,DataBits = 8,StopBits = StopBits.One,Handshake = Handshake.RequestToSend, // PLC常用硬件流控RtsEnable = true, // 启用RTS信号ReadTimeout = 2000,NewLine = "\r\n" // PLC文本协议常用换行符};// 绑定接收事件_plcPort.DataReceived += PlcPort_DataReceived;}
​public void StartComm(){try{if (!_plcPort.IsOpen) _plcPort.Open();Log("串口已打开,等待PLC数据...");// 发送PLC读取指令(示例:读取状态寄存器)byte[] readCmd = { 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x28, 0x0A };_plcPort.Write(readCmd, 0, readCmd.Length);}catch (UnauthorizedAccessException){Log("错误:串口被占用或无权限");}catch (IOException){Log("错误:串口不存在或设备未连接");}}
​// 接收事件(子线程,需跨UIInvoke)private void PlcPort_DataReceived(object sender, SerialDataReceivedEventArgs e){if (_plcPort.BytesToRead == 0) return;byte[] recvData = new byte[_plcPort.BytesToRead];_plcPort.Read(recvData, 0, recvData.Length);// 跨UI线程更新日志_logTextBox.Invoke(new Action(() => Log($"收到PLC数据:{BitConverter.ToString(recvData)}")));}
​private void Log(string msg) => _logTextBox.AppendText($"[{DateTime.Now:HH:mm:ss}] {msg}\r\n");
}

2. SerialDataReceivedEventArgs(串口接收事件参数)

命名空间System.IO.Ports

核心功能:为SerialPort.DataReceived事件提供上下文,区分接收数据类型。

关键 API

属性名说明
EventType接收数据类型(枚举SerialData):- Chars:常规字符 / 字节数据(99% 场景)- Eof:流结束符(仅部分设备支持,如 Ctrl+Z)

示例(根据数据类型处理)

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{var port = sender as SerialPort;if (port == null || !port.IsOpen) return;
​switch (e.EventType){case SerialData.Chars:// 处理常规字节数据byte[] data = new byte[port.BytesToRead];port.Read(data, 0, data.Length);Console.WriteLine($"接收字节:{BitConverter.ToString(data)}");break;case SerialData.Eof:// 处理流结束(如设备断开连接的信号)Console.WriteLine("收到流结束符,设备可能已断开");port.Close();break;}
}

3. ModbusSerialMaster(Modbus RTU 主站)

命名空间Modbus.Device(第三方库NModbus,需通过 NuGet 安装:Install-Package NModbus

核心功能:封装 Modbus RTU 协议(串口),简化 “主站 - 从站” 通信(如读取传感器寄存器、控制 PLC 输出)。

关键 API(Modbus 核心功能)

方法名说明
CreateRtu(SerialPort serialPort)静态方法:通过已初始化的SerialPort创建 RTU 主站实例
ReadHoldingRegisters(byte slaveAddr, ushort startAddr, ushort count)读取保持寄存器(地址 0-65535,返回ushort[],对应 Modbus 功能码 03)
ReadInputRegisters(byte slaveAddr, ushort startAddr, ushort count)读取输入寄存器(只读,对应功能码 04)
ReadCoils(byte slaveAddr, ushort startAddr, ushort count)读取线圈(开关量,0=OFF/1=ON,对应功能码 01)
WriteSingleRegister(byte slaveAddr, ushort regAddr, ushort value)写入单个保持寄存器(对应功能码 06)
WriteMultipleCoils(byte slaveAddr, ushort startAddr, bool[] values)写入多个线圈(对应功能码 15)
Transport.ReadTimeout/WriteTimeout通信超时(毫秒,默认 1000,需根据设备响应调整)

示例(RTU 主站读取温湿度传感器)

using System;
using System.IO.Ports;
using Modbus.Device;
​
class ModbusRtuSensorReader
{static void Main(){// 1. 初始化串口(与传感器RTU参数一致)using (var serialPort = new SerialPort("COM5"){BaudRate = 9600,Parity = Parity.None,DataBits = 8,StopBits = StopBits.One,ReadTimeout = 3000}){serialPort.Open();
​// 2. 创建RTU主站using (var master = ModbusSerialMaster.CreateRtu(serialPort)){master.Transport.ReadTimeout = 2000; // 延长超时(传感器可能响应慢)byte slaveAddr = 1; // 传感器从站地址(硬件配置,如拨码开关)
​try{// 3. 读取寄存器:温度(地址0)、湿度(地址1)(功能码03)ushort[] registers = master.ReadHoldingRegisters(slaveAddr, 0, 2);// 4. 解析数据(假设传感器返回值为“数值*0.1”,如0x01F4=500 → 50.0℃)float temperature = registers[0] * 0.1f;float humidity = registers[1] * 0.1f;Console.WriteLine($"当前温度:{temperature:0.0}℃,湿度:{humidity:0.0}%");}catch (ModbusTimeoutException){Console.WriteLine("错误:传感器无响应(超时)");}catch (ModbusSlaveException ex){Console.WriteLine($"传感器异常:功能码{ex.SlaveExceptionCode}(如地址无效)");}}}}
}

4. ModbusIpMaster(Modbus TCP 主站)

命名空间Modbus.DeviceNModbus库)

核心功能:封装 Modbus TCP 协议(以太网),用于主站与 TCP 从站(如 Modbus 网关、工业交换机)通信,无需串口硬件。

关键 API(与 RTU 差异点)

方法名说明
CreateIp(TcpClient tcpClient)静态方法:通过TcpClient创建 TCP 主站(TCP 连接替代串口)
ReadHoldingRegisters(byte unitId, ushort startAddr, ushort count)读取保持寄存器(参数unitId替代 RTU 的slaveAddr,对应 TCP 帧的 “单元 ID”)
其他方法(如WriteSingleRegister参数与 RTU 一致,仅底层协议为 TCP(端口默认 502)

示例(TCP 主站控制 Modbus 网关输出)

using System;
using System.Net.Sockets;
using Modbus.Device;
​
class ModbusTcpGatewayControl
{static void Main(){// 1. 连接Modbus TCP从站(网关IP:192.168.1.200,端口502)using (var tcpClient = new TcpClient()){tcpClient.Connect("192.168.1.200", 502);Console.WriteLine("已连接Modbus网关");
​// 2. 创建TCP主站using (var master = ModbusIpMaster.CreateIp(tcpClient)){byte unitId = 1; // 网关单元ID(配置工具设置)try{// 3. 控制网关继电器(写入线圈:地址0=ON,对应功能码15)bool[] relayStates = { true }; // 继电器1闭合master.WriteMultipleCoils(unitId, 0, relayStates);Console.WriteLine("继电器1已闭合");
​// 4. 验证状态(读取线圈,确认是否生效)bool[] currentStates = master.ReadCoils(unitId, 0, 1);Console.WriteLine($"继电器当前状态:{(currentStates[0] ? "ON" : "OFF")}");}catch (SocketException){Console.WriteLine("错误:网关断开连接或IP/端口错误");}}}}
}

5. Socket(底层网络通信)

命名空间System.Net.Sockets

核心功能:最底层的网络通信类,支持 TCP/UDP/RAW 协议,灵活控制字节流,适合自定义协议开发(如物联网私有协议)。

关键 API(TCP/UDP 通用)

类别名称及说明
初始化Socket(AddressFamily family, SocketType type, ProtocolType protocol):- familyInterNetwork(IPv4)/InterNetworkV6(IPv6)- typeStream(TCP,面向连接)/Dgram(UDP,无连接)- protocolTcp/Udp
TCP 操作Bind(EndPoint localEp):绑定本地 IP + 端口(服务器必用)Listen(int backlog):开始监听(服务器,backlog为最大等待队列)Accept()/AcceptAsync():接受客户端连接(返回新Socket用于通信)Connect(EndPoint remoteEp):客户端连接服务器
UDP 操作SendTo(byte[] buffer, EndPoint remoteEp):发送 UDP 数据报到指定端点(无需连接)ReceiveFrom(byte[] buffer, ref EndPoint remoteEp):接收 UDP 数据报(获取发送端地址)
通用操作Send(byte[] buffer):TCP 发送数据(需先连接)Receive(byte[] buffer):读取数据(TCP 阻塞,UDP 需用ReceiveFromSetSocketOption(SocketOptionLevel level, SocketOptionName name, object value):设置选项(如ReuseAddress允许端口复用)Shutdown(SocketShutdown how):关闭发送 / 接收通道(Send/Receive/BothClose():关闭 Socket(释放资源)

示例(UDP 自定义协议数据收发)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
​
class UdpCustomProtocol
{static void Main(){// UDP Socket(IPv4,无连接)using (var udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)){// 绑定本地端口(接收用,发送可省略)IPEndPoint localEp = new IPEndPoint(IPAddress.Any, 9000);udpSocket.Bind(localEp);Console.WriteLine("UDP Socket已绑定端口9000,等待数据...");
​// 1. 接收客户端数据byte[] recvBuffer = new byte[1024];EndPoint clientEp = new IPEndPoint(IPAddress.Any, 0); // 用于存储发送端地址int recvLen = udpSocket.ReceiveFrom(recvBuffer, ref clientEp);string recvMsg = Encoding.UTF8.GetString(recvBuffer, 0, recvLen);Console.WriteLine($"收到来自{clientEp}的消息:{recvMsg}");
​// 2. 发送响应(自定义协议:前缀"ACK:")string response = $"ACK:{recvMsg}";byte[] sendBuffer = Encoding.UTF8.GetBytes(response);udpSocket.SendTo(sendBuffer, clientEp);Console.WriteLine("已发送响应");}}
}

6. TcpListener(TCP 服务器封装)

命名空间System.Net.Sockets

核心功能:封装Socket的 TCP 服务器逻辑(Bind/Listen/Accept),简化服务器开发,无需直接操作底层Socket

关键 API

方法名说明
TcpListener(IPAddress localAddr, int port)构造函数:绑定本地 IP(IPAddress.Any表示所有网卡)和端口
Start()/Stop()启动 / 停止监听(Stop()会关闭所有已接受的TcpClient
AcceptTcpClient()/AcceptTcpClientAsync()接受客户端连接(返回TcpClient,用于与该客户端通信)- 同步方法阻塞,异步方法适合高并发
Pending()检查是否有等待连接(返回bool,非阻塞,用于轮询)

示例(异步 TCP 服务器,支持多客户端)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
​
class AsyncTcpServer
{static async Task Main(){// 监听所有网卡的8080端口var listener = new TcpListener(IPAddress.Any, 8080);listener.Start();Console.WriteLine("TCP服务器已启动,等待客户端连接...");
​try{// 循环接受客户端(异步,不阻塞)while (true){TcpClient client = await listener.AcceptTcpClientAsync();Console.WriteLine($"新客户端连接:{client.Client.RemoteEndPoint}");// 单独线程处理客户端(避免阻塞接受新连接)_ = HandleClientAsync(client); // _ 忽略Task返回值(后台处理)}}finally{listener.Stop();}}
​// 异步处理单个客户端通信private static async Task HandleClientAsync(TcpClient client){using (client) // 自动释放客户端资源using (NetworkStream stream = client.GetStream()){byte[] buffer = new byte[1024];int bytesRead;// 循环读取客户端数据(直到客户端断开)while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0){string clientMsg = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"来自{client.Client.RemoteEndPoint}:{clientMsg}");
​// 发送响应string response = $"Server Echo: {clientMsg}";byte[] responseBuffer = Encoding.UTF8.GetBytes(response);await stream.WriteAsync(responseBuffer, 0, responseBuffer.Length);}Console.WriteLine($"客户端{client.Client.RemoteEndPoint}已断开");}}
}

7. UdpClient(UDP 封装)

命名空间System.Net.Sockets

核心功能:封装Socket的 UDP 操作,简化数据报收发,支持多播 / 广播,无需手动处理Socket选项。

关键 API(补充多播 / 广播)

类别名称及说明
基础操作UdpClient(int port):绑定本地端口(接收必用)Send(byte[] dgram, int bytes, IPEndPoint remoteEp):发送数据报到指定端点Receive(ref IPEndPoint remoteEp)/ReceiveAsync():接收数据报(获取发送端地址)
多播支持JoinMulticastGroup(IPAddress multicastAddr):加入多播组(如224.0.0.100,多设备共享数据)LeaveMulticastGroup(IPAddress multicastAddr):离开多播组
广播支持EnableBroadcast = true:启用广播(必须设置,否则无法发送广播包)广播地址:IPAddress.Broadcast255.255.255.255,局域网所有设备)

示例(UDP 多播数据分发)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
​
class UdpMulticastDemo
{// 多播组地址(需在224.0.0.0~239.255.255.255范围内)private static readonly IPAddress _multicastAddr = IPAddress.Parse("224.0.0.100");private const int _multicastPort = 9001;
​// 多播发送端(如数据采集器)static async Task SenderAsync(){using (var udpClient = new UdpClient()){udpClient.EnableBroadcast = false; // 多播无需广播IPEndPoint multicastEp = new IPEndPoint(_multicastAddr, _multicastPort);
​// 循环发送数据(每秒1次)for (int i = 0; i < 10; i++){string data = $"Multicast Data {i} - {DateTime.Now:HH:mm:ss}";byte[] buffer = Encoding.UTF8.GetBytes(data);await udpClient.SendAsync(buffer, buffer.Length, multicastEp);Console.WriteLine($"发送多播数据:{data}");await Task.Delay(1000);}}}
​// 多播接收端(如多个监控终端)static async Task ReceiverAsync(string receiverName){using (var udpClient = new UdpClient(_multicastPort)){// 加入多播组(必须操作,否则收不到多播数据)udpClient.JoinMulticastGroup(_multicastAddr);Console.WriteLine($"{receiverName}已加入多播组,等待数据...");
​IPEndPoint senderEp = new IPEndPoint(IPAddress.Any, 0);while (true){// 异步接收多播数据UdpReceiveResult result = await udpClient.ReceiveAsync();string data = Encoding.UTF8.GetString(result.Buffer);Console.WriteLine($"{receiverName}收到:{data}(来自{result.RemoteEndPoint})");}}}
​static void Main(){// 启动发送端和两个接收端(多线程)_ = SenderAsync();_ = ReceiverAsync("监控终端1");_ = ReceiverAsync("监控终端2");Console.ReadLine(); // 阻塞主线程}
}

8. Stream(抽象流基类)

命名空间System.IO

核心功能:所有字节流的抽象基类(如NetworkStream/FileStream/MemoryStream),定义统一的读写接口,支持 “多态” 操作(如用同一逻辑处理网络流和文件流)。

关键 API(抽象方法,子类实现)

方法 / 属性说明
核心操作Read(byte[] buffer, int offset, int count):从流读字节(返回实际读取长度,0 表示流结束)Write(byte[] buffer, int offset, int count):向流写字节Flush():刷新缓冲区(网络流 / 文件流需调用,避免数据滞留)
状态判断CanRead/CanWrite:是否支持读写(如断开的NetworkStreamfalseCanSeek:是否支持定位(NetworkStreamfalseFileStreamtrueLength:流长度(仅CanSeek=true可用)
异步操作ReadAsync(byte[] buffer, int offset, int count)/WriteAsync(...):异步读写(非阻塞)CopyToAsync(Stream destination):异步复制流数据(如网络流→文件流)

示例(多态处理流:网络流保存到文件)

using System;
using System.IO;
using System.Net.Sockets;
using System.Threading.Tasks;
​
class StreamPolymorphismDemo
{// 通用流保存方法(接收任何Stream子类)private static async Task SaveStreamToFileAsync(Stream sourceStream, string filePath){if (!sourceStream.CanRead)throw new InvalidOperationException("流不支持读取");
​// 用FileStream作为目标流(多态:sourceStream可为NetworkStream/MemoryStream等)using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)){Console.WriteLine($"开始保存流到:{filePath}");await sourceStream.CopyToAsync(fileStream); // 异步复制(自动处理缓冲)await fileStream.FlushAsync(); // 确保数据写入磁盘Console.WriteLine("保存完成");}}
​static async Task Main(){// 1. 从TCP服务器获取网络流using (var tcpClient = new TcpClient()){await tcpClient.ConnectAsync("192.168.1.300", 8080);using (NetworkStream netStream = tcpClient.GetStream()){// 2. 调用通用方法,将网络流保存到本地文件await SaveStreamToFileAsync(netStream, "received_data.bin");}}
​// 3. 测试:用MemoryStream调用同一方法(多态验证)using (var memoryStream = new MemoryStream()){// 向内存流写入测试数据byte[] testData = System.Text.Encoding.UTF8.GetBytes("Test Memory Stream Data");await memoryStream.WriteAsync(testData, 0, testData.Length);memoryStream.Position = 0; // 重置流指针(否则Read会从末尾开始)// 保存内存流到文件await SaveStreamToFileAsync(memoryStream, "memory_data.txt");}}
}

9. Encoding(字符编码)

命名空间System.Text

核心功能:处理 “字符串 - 字节数组” 转换,解决多语言编码问题(如中文 UTF-8/GB2312、英文 ASCII),是通讯中 “文本协议” 的核心工具。

关键 API(补充编码兼容性)

类别名称及说明
预定义编码Encoding.UTF8:UTF-8 编码(推荐,支持所有语言,无 BOM)Encoding.ASCII:ASCII 编码(仅英文,中文转?Encoding.Unicode:UTF-16 编码(双字节,Windows 内部常用)Encoding.Default:系统默认编码(Windows=GB2312,Linux=UTF-8,跨平台不推荐
自定义编码Encoding.GetEncoding(int codePage):通过代码页获取编码(如936=GB2312,65001=UTF-8,950=Big5)Encoding.GetEncoding(string name):通过名称获取(如"gb2312"/"utf-8"
转换操作GetBytes(string s):字符串→字节数组GetString(byte[] bytes, int index, int count):字节数组→字符串(指定起始位置和长度,避免冗余数据)GetByteCount(string s):计算字符串对应的字节长度(预分配缓冲区,提升性能)

示例(多编码转换:GB2312 与 UTF-8 互转)

using System;
using System.Text;class EncodingConversionDemo
{static void Main(){// 原始中文字符串string chineseText = "通讯测试:C# Encoding";// 1. UTF-8 → GB2312(如向旧设备发送GB2312数据)byte[] utf8Bytes = Encoding.UTF8.GetBytes(chineseText);// 先将UTF-8字节转成字符串(避免编码丢失),再转GB2312string tempText = Encoding.UTF8.GetString(utf8Bytes);byte[] gb2312Bytes = Encoding.GetEncoding(936).GetBytes(tempText);Console.WriteLine($"UTF-8→GB2312字节:{BitConverter.ToString(gb2312Bytes)}");// 2. GB2312 → UTF-8(如接收旧设备GB2312数据,转UTF-8显示)string gb2312Text = Encoding.GetEncoding(936).GetString(gb2312Bytes);byte[] utf8Bytes2 = Encoding.UTF8.GetBytes(gb2312Text);string finalText = Encoding.UTF8.GetString(utf8Bytes2);Console.WriteLine($"GB2312→UTF-8结果:{finalText}");// 3. 避免常见错误:直接用错误编码解析string wrongText = Encoding.ASCII.GetString(gb2312Bytes);Console.WriteLine($"错误编码(ASCII)解析结果:{wrongText}"); // 中文显示为?}
}

10. Dns(域名解析)

命名空间System.Net

核心功能:将域名(如www.baidu.com)解析为 IP 地址,或反向解析 IP 到域名,是网络通信中 “域名转 IP” 的核心类。

关键 API(异步优先)

方法名说明
正向解析GetHostAddressesAsync(string hostNameOrAddress):异步解析域名到 IP 数组(支持 IPv4/IPv6,返回IPAddress[]GetHostEntryAsync(string hostNameOrAddress):异步获取主机条目(包含 IP、主机名、别名,返回IPHostEntry
反向解析GetHostEntryAsync(IPAddress address):异步将 IP 解析为域名(依赖 DNS 反向记录,可能返回空)
同步方法GetHostAddresses(string hostName)/GetHostEntry(string hostName):同步解析(不推荐,会阻塞线程)

示例(异步解析域名并连接服务器)

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;class DnsResolverDemo
{static async Task Main(){string domain = "www.baidu.com"; // 待解析域名int port = 80; // HTTP端口try{// 1. 异步解析域名(获取所有IP地址)Console.WriteLine($"正在解析域名:{domain}");IPAddress[] ipAddresses = await Dns.GetHostAddressesAsync(domain);// 筛选IPv4地址(避免IPv6连接问题)IPAddress ipv4Addr = Array.Find(ipAddresses, ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);if (ipv4Addr == null){Console.WriteLine("未找到IPv4地址");return;}Console.WriteLine($"解析到IPv4地址:{ipv4Addr}");// 2. 用解析后的IP连接服务器using (var tcpClient = new TcpClient()){await tcpClient.ConnectAsync(ipv4Addr, port);Console.WriteLine($"已连接到 {domain}({ipv4Addr}:{port})");}}catch (SocketException ex){Console.WriteLine($"连接错误:{ex.Message}");}catch (Exception ex){Console.WriteLine($"解析错误:{ex.Message}(如域名不存在、DNS不可用)");}}
}

11. IPAddress(IP 地址封装)

命名空间System.Net

核心功能:表示 IPv4/IPv6 地址,提供地址解析、验证、格式转换,是IPEndPointSocket的基础参数。

关键 API(补充地址验证与转换)

类别名称及说明
地址创建IPAddress.Parse(string ipString):解析 IP 字符串(如"192.168.1.1"),无效则抛FormatException``IPAddress.TryParse(string ipString, out IPAddress result):安全解析(返回bool,不抛异常,推荐)
预定义地址IPAddress.Any:匹配所有本地网卡 IP(服务器绑定用,如0.0.0.0IPAddress.Loopback:回环地址(127.0.0.1,本地测试用)IPAddress.Broadcast:广播地址(255.255.255.255,UDP 广播用)
属性AddressFamily:地址族(InterNetwork=IPv4,InterNetworkV6=IPv6)IsIPv4MappedToIPv6:是否为 IPv4 映射的 IPv6 地址ToString():将 IP 地址转为字符串(如"192.168.1.1"

示例(IP 地址验证与筛选)

using System;
using System.Net;
using System.Linq;class IPAddressValidationDemo
{static void Main(){// 1. 安全解析IP(避免异常)string[] testIps = { "192.168.1.100", "256.0.0.1", "fe80::1", "invalid.ip" };foreach (string ipStr in testIps){if (IPAddress.TryParse(ipStr, out IPAddress ip)){string ipType = ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? "IPv4" : "IPv6";Console.WriteLine($"有效{ipType}地址:{ip}");}else{Console.WriteLine($"无效IP地址:{ipStr}");}}// 2. 解析域名后筛选IPv4(结合Dns)IPAddress[] baiduIps = Dns.GetHostAddresses("www.baidu.com");IPAddress[] baiduIpv4 = baiduIps.Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToArray();Console.WriteLine($"\n百度IPv4地址列表:{string.Join(", ", baiduIpv4)}");// 3. 回环地址测试(本地服务)IPAddress loopback = IPAddress.Loopback;Console.WriteLine($"回环地址:{loopback}(用于本地程序通信)");}
}

12. NetworkStream(网络流)

命名空间System.Net.Sockets

核心功能:封装Socket的网络数据流,支持 TCP/UDP(主要用于 TCP)的字节读写,继承自Stream,可与其他流类(如FileStream)协同工作。

关键 API(补充超时与状态)

类别名称及说明
构造与状态NetworkStream(Socket socket):通过Socket创建网络流CanTimeout:是否支持超时(始终trueReadTimeout/WriteTimeout:读写超时(毫秒,默认无限期,需手动设置避免阻塞)
流操作Read(byte[] buffer, int offset, int count):读取网络数据(TCP 阻塞,UDP 需用UdpClientWrite(byte[] buffer, int offset, int count):发送网络数据Flush():刷新缓冲区(TCP 需调用,确保数据发送)
连接控制Close(int timeout):关闭流并等待指定时间(毫秒),确保数据发送完成Dispose(bool disposing):释放资源(using语句自动调用)

示例(带超时的 TCP 网络流读写)

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;class NetworkStreamTimeoutDemo
{static async Task Main(){using (var tcpClient = new TcpClient()){try{// 连接超时(需通过TcpClient.ConnectAsync的CancellationToken实现)var connectTask = tcpClient.ConnectAsync("192.168.1.400", 8080);if (await Task.WhenAny(connectTask, Task.Delay(3000)) != connectTask){throw new TimeoutException("连接超时(3秒)");}using (NetworkStream netStream = tcpClient.GetStream()){// 设置流超时(避免Read/Write无限阻塞)netStream.ReadTimeout = 2000;netStream.WriteTimeout = 2000;// 发送数据string sendMsg = "Hello NetworkStream with Timeout";byte[] sendBuffer = Encoding.UTF8.GetBytes(sendMsg);await netStream.WriteAsync(sendBuffer, 0, sendBuffer.Length);await netStream.FlushAsync();Console.WriteLine($"已发送:{sendMsg}");// 接收响应(带超时)byte[] recvBuffer = new byte[1024];int recvLen = await netStream.ReadAsync(recvBuffer, 0, recvBuffer.Length);if (recvLen == 0){Console.WriteLine("服务器关闭连接");return;}string recvMsg = Encoding.UTF8.GetString(recvBuffer, 0, recvLen);Console.WriteLine($"收到响应:{recvMsg}");}}catch (TimeoutException ex){Console.WriteLine($"超时错误:{ex.Message}");}catch (SocketException ex){Console.WriteLine($"网络错误:{ex.Message}");}}}
}

13. IPEndPoint(IP 端点)

命名空间System.Net

核心功能:表示 “IP 地址 + 端口” 的组合,标识网络中的唯一端点(如服务器192.168.1.1:8080),是SocketUdpClientTcpListener的核心参数。

关键 API

类别名称及说明
构造函数IPEndPoint(IPAddress address, int port):创建端点(port范围 1-65535,0 为随机端口)
属性Address:获取端点的IPAddress对象Port:获取端点的端口号AddressFamily:获取地址族(与Address一致)ToString():转为字符串(如"192.168.1.1:8080"
静态方法Create(EndPoint endPoint):将通用EndPoint转为IPEndPoint(类型转换)

示例(创建本地 / 远程端点并通信)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;class IPEndPointDemo
{static void Main(){// 1. 创建远程端点(服务器地址)IPAddress serverIp = IPAddress.Parse("192.168.1.500");int serverPort = 9002;IPEndPoint serverEp = new IPEndPoint(serverIp, serverPort);Console.WriteLine($"远程服务器端点:{serverEp}");// 2. 创建本地端点(客户端绑定固定端口,可选)IPAddress localIp = IPAddress.Any; // 自动选择本地IPint localPort = 9003;IPEndPoint localEp = new IPEndPoint(localIp, localPort);Console.WriteLine($"本地客户端端点:{localEp}");// 3. 用Socket绑定本地端点并连接远程端点using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)){socket.Bind(localEp); // 绑定本地端口(客户端可选,服务器必选)socket.Connect(serverEp);Console.WriteLine("已连接到服务器");// 发送数据byte[] data = Encoding.UTF8.GetBytes("Hello IPEndPoint");socket.Send(data);Console.WriteLine("已发送数据");// 接收响应byte[] recvBuffer = new byte[1024];int recvLen = socket.Receive(recvBuffer);string recvMsg = Encoding.UTF8.GetString(recvBuffer, 0, recvLen);Console.WriteLine($"收到响应:{recvMsg}");}}
}

补充说明(实际开发必看)

  1. 资源释放:所有实现IDisposable的类(如SerialPortSocketStream)必须用using语句包裹,避免端口 / 句柄泄漏。

  2. 异步优先:UI 程序或高并发服务需用Async/Await(如ConnectAsyncReadAsync),避免主线程阻塞。

  3. 异常处理:

    • 串口:UnauthorizedAccessException(权限)、IOException(设备断开)、TimeoutException(超时)

    • 网络:SocketException(IP / 端口错误、断网)、TimeoutException(连接 / 读写超时)

    • Modbus:ModbusTimeoutException(从站无响应)、ModbusSlaveException(从站异常码)

  4. 库依赖:Modbus 类需安装NModbus,NuGet 命令:Install-Package NModbus(.NET Framework)或Install-Package NModbus4(.NET Core/.NET 5+)。

  5. 编码注意:中文通信优先用 UTF-8,旧设备用 GB2312(代码页 936),避免乱码。

http://www.dtcms.com/a/465944.html

相关文章:

  • 网站开发说明书天元建设集团有限公司申请破产了吗
  • 分布式单例模式在微服务架构中的关键作用与实践
  • 网站footer模板建设银行甘肃省行网站
  • 网站建设和电商区别wordpress创建角色
  • 网站开发软件公司网站建设运营公司
  • Java开发环境搭建及基础练习
  • 【三维重建】即插即用的3DGS的PDE优化:高质量渲染和重建
  • TDS:连接器漫谈之可信空间中的沉默契约与隐秘通道
  • AI Compass前沿速览:DeepSeek-V3.2、Sora 2、Imagine v0.9、LONGLIVE–英伟达、xLLM、OpenAgents
  • 为什么要建设图书馆网站网站建设情况的报告
  • linux之 remoteproc 内核实现源码分析
  • vue 识别一个高亮组件全局
  • RFID与机械臂协同:构建智能产品溯源新范式
  • 生活馆网站开发背景网站制作如皋
  • 第二章数据预处理:公式Python代码实现
  • CSS的重绘和重排是什么?如何减少css的重绘和重排?
  • 哪个网站可以做专业兼职程序员用的编程软件
  • 国内云服务器免费优化培训学校
  • Linux多进程:查看当前哪个进程正在使用共享数据区的互斥锁文件
  • 【MySQL SQL语句实战】设计表,建表语句,数据插入,实战案例包括:简单查询、汇总统计、分组分析、多表关联、窗口函数
  • 系统设计-高频面试题(更新中...)
  • IntelliJ IDEA使用经验(十五):SQL脚本文件转为数据库控制台
  • 【实时Linux实战系列】内核跟踪点(Tracepoints)与用户态探针(UST)的协同调试
  • Linux 进程通信——消息队列与信号量
  • 备案ip 查询网站查询网站小说一键生成动漫
  • 做养生产品哪个网站好嘉兴网站建设网址
  • Vue3中实现全局双向绑定变量
  • C语言数据结构-排序
  • 【三维重建-对极几何】极线约束(Epipolar Constraint)
  • LeetCode算法日记 - Day 68: 猜数字大小II、矩阵中的最长递增路径