c#软件开发学习笔记--TcpListener\TcpClient\UdpClient
TCP / UDP 设备连接学习总结一、TcpListener —— 服务器端客户端 服务器 (TcpListener) │ │ │ ───① new TcpListener(ip, port) │ │ ───② .Start() 开始监听 ────────── │ │ │ │ ◄─── AcceptTcpClientAsync() 阻塞等待 │ │ │ │ ───③ TcpClient.ConnectAsync() ──► │ │ │ │ ◄── 返回 TcpClient 实例 ───────── │ │ │ │ ───④ GetStream() 获取 NetworkStream │ │ │ │ ═════⑤ ReadAsync() / WriteAsync() ═══数据交换═════ │ │ │ ───⑥ 停止: Stop() 停止监听 ─────── │ │ │1.1 关键方法与属性成员说明new TcpListener(IPAddress, int port)构造绑定本地 IP 与端口Start()开始监听Stop()停止监听Pending()是否有挂起的连接请求常用于循环里非阻塞判断AcceptTcpClient()/AcceptTcpClientAsync()同步/异步接受一个连接返回TcpClientAcceptTcpClientAsync(CancellationToken)支持取消令牌的异步接受.NET 9 项目中使用1.2 基础实现TCPListen业务TCP 服务器收到客户端数据 → 写入串口串口返回数据 → 回发给当前客户端。使用ConcurrentQueue把多个客户端请求串行化避免串口并发冲突。// 启动监听tcpListennewTcpListener(IPAddress.Parse(192.168.219.14),9999);tcpListen.Start();// 异步循环接受连接privatevoidAcceptRequest(){ctsnewCancellationTokenSource();Task.Run(async(){while(!cts.IsCancellationRequested){if(tcpListennull)break;if(tcpListen.Pending())continue;// 若挂起连接则跳过TcpClienttcpClientawaittcpListen.AcceptTcpClientAsync();AcceptData(tcpClient);// 转入数据接收循环}},cts.Token);}// 读取客户端数据并通过 NetworkStream 回写串口响应NetworkStreamstreamcurrentClient.GetStream();stream.Write(fullFrame,0,fullFrame.Length);1.3 完整设备服务器实现TCPListen连接设备服务器在基础版上增加了配置持久化FileIni、本机 IP 自动识别、收发字节计数、Modbus 帧按功能码解析0x03读 /0x06写、带CancellationToken的异步 API。// 自动获取本机 IPv4 地址用于监听IPAddress[]addressesDns.GetHostAddresses(Dns.GetHostName());foreach(IPAddressaddressinaddresses)if(address.AddressFamilyAddressFamily.InterNetwork)txtServerIP.Textaddress.ToString();// 启动tcpListenernewTcpListener(IPAddress.Parse(txtServerIP.Text),int.Parse(txtPort.Text));tcpListener.Start();// 带取消令牌的异步接受TcpClientclientawaittcpListener.AcceptTcpClientAsync(_cts.Token);// 带取消令牌的异步读取NetworkStreamstreamclient.GetStream();intlenawaitstream.ReadAsync(buffer,_cts.Token);if(len0)return;// len0 表示客户端已正常断开// 回写响应异步awaitstream.WriteAsync(fullFrame);停止服务器时释放资源privatevoidStopServer(){_cts?.Cancel();serialPort?.Close();tcpListener?.Stop();// 停止监听tcpListenernull;}二、TcpClient —— 客户端客户端 (TcpClient) 服务器 │ │ │ ───① new TcpClient() ───────────── │ │ │ │ ───② .ConnectAsync(host, port) ─► │ AcceptTcpClientAsync() │ │ │ ◄── 连接成功 (Connectedtrue) ──── │ │ │ │ ───③ GetStream() 获取 NetworkStream │ │ │ │ ───④ Write() / WriteAsync() 发送 ──► │ ReadAsync() 接收 │ │ │ ◄──⑤ ReadAsync() 接收响应 ───────── │ WriteAsync() 回写 │ │ │ ═════ 循环收发 ═══════════════════ │ │ │ │ ───⑥ 停止: Close() 关闭连接 ────── │ │ │2.1 关键方法与属性成员说明new TcpClient()构造一个未连接的客户端Connect(host, port)/ConnectAsync(host, port)同步/异步连接服务器Connected(bool)当前是否处于连接状态Available(int)网络缓冲区中可读字节数GetStream()返回NetworkStream用于读写Client(Socket)底层 Socket可取RemoteEndPoint等信息Close()关闭连接NetworkStream关键成员Read / ReadAsync返回 0 表示对端关闭、Write / WriteAsync。2.2 基础实现TCPClient业务连接服务器 → 后台循环接收 → 定时器周期性发送。// 连接privateasyncTaskConnectServer(){tcpClientnewTcpClient();awaittcpClient.ConnectAsync(192.168.219.14,9999);}// 接收循环Available 判断 ReadAsyncprivatevoidAcceptData(){ctsnewCancellationTokenSource();Task.Run(async(){byte[]buffernewbyte[1024];while(!cts.IsCancellationRequested){if(tcpClientnull||!tcpClient.Connected)continue;NetworkStreamstreamtcpClient.GetStream();intlenawaitstream.ReadAsync(buffer,0,buffer.Length,cts.Token);if(len0)break;// 处理 buffer[0..len)}},cts.Token);}// 发送NetworkStreamstreamtcpClient.GetStream();byte[]bsEncoding.UTF8.GetBytes(textBox1.Text);stream.Write(bs,0,bs.Length);2.3 设备客户端实现TCPClient连接设备客户端业务通过 TCP 承载 Modbus RTU 协议——组装请求帧功能码0x03读 /0x06写CRCHelper.CRC16校验发送后解析响应。发送使用lock(sendLock)保证线程安全。// 连接含异常提示awaitclient.ConnectAsync(txtServerIP.Text,int.Parse(txtPort.Text));// 发送 Modbus 读保持寄存器请求功能码 0x03privatevoidSendRequest(ushortslaveAddress,ushortstartAddress,ushortdataLength){lock(sendLock){if(clientnull)return;byte[]bsnewbyte[8];bs[0](byte)slaveAddress;bs[1]0X03;bs[2](byte)(startAddress8);bs[3](byte)(startAddress0XFF);bs[4](byte)(dataLength8);bs[5](byte)(dataLength0XFF);byte[]crcCRCHelper.CRC16(bs);bs[6]crc[0];bs[7]crc[1];client.GetStream().Write(bs);}}// 接收并按功能码解析响应intfuncCodebuffer[1];if(funcCode0X03){/* 解析寄存器值 */}elseif(funcCode0X06){/* 解析写入回显 */}断开连接privatevoidDisConnectServer(){_cts?.Cancel();client?.Close();clientnull;}三、UdpClient —— 无连接收发客户端 (UdpClient) 服务器 (UdpClient) │ │ │ ───① new UdpClient(任意端口) │ │ │ │ ───② 构造 IPEndPoint(server, port) │ │ │ │ ───③ Send(data, len, endPoint) ─► │ ReceiveAsync() 阻塞等待 │ │ │ │ 获得 RemoteEndPoint │ │ │ ◄──④ ReceiveAsync() 收到响应 ───── │ Send(data, len, remoteEndPoint) │ │ │ │ │ ═════ 无需连接直接数据报收发 ════ │ │ │ │ ───⑤ 停止: Close() / Dispose() ─── │ │ │UDP 不需要建立连接服务器与客户端的区别仅在于服务器绑定固定端口并ReceiveAsync等待数据客户端绑定任意端口IPAddress.Any, 0后用Send指定目标端点。3.1 关键方法与属性成员说明new UdpClient(IPEndPoint)构造并绑定本地端点Send(byte[], int, IPEndPoint)向指定远程端点发送数据报ReceiveAsync()异步接收返回UdpReceiveResult含Buffer与RemoteEndPointClose()/Dispose()释放资源3.2 UDP 客户端业务向设备发送 Modbus 请求帧异步接收并解析响应寄存器值。// 绑定本地任意端口目标端点由 endPoint 指定clientnewUdpClient(newIPEndPoint(IPAddress.Any,0));endPointnewIPEndPoint(IPAddress.Parse(txtIp.Text),int.Parse(txtPort.Text));// 发送client.Send(bytes,bytes.Length,endPoint);// 异步接收varresawaitclient.ReceiveAsync();if(res.Buffer[1]!0X03)continue;intbyteCountres.Buffer[2];// 解析寄存器值...3.3 UDP 服务器业务UDP 服务器收到客户端请求 → 写串口 → 串口返回数据 → 用Send回发给该客户端RemoteEndPoint。同样用ConcurrentQueue串行化串口访问。// 绑定本机 IP 9999 端口servernewUdpClient(newIPEndPoint(address,9999));// 接收循环varresawaitserver.ReceiveAsync();requestQueue.Enqueue(newRequestItem{clientEndPointres.RemoteEndPoint,datares.Buffer});// 串口响应回发给对应客户端server.Send(fullFrame,fullFrame.Length,currentRequest.clientEndPoint);四、通用设计模式总结4.1 异步接收循环统一范式所有子项目都采用相同范式CancellationTokenSourceTask.Runwhile(!cts.IsCancellationRequested)循环 await XxxAsync(cts.Token)。这是 WinForms 下避免阻塞 UI 线程的标准做法。4.2 请求队列 串行化处理串口是独占资源不能并发写入。服务器端统一使用ConcurrentQueueRequestItemlockisProcessing标志位把并发的网络请求排成队列逐个转发给串口串口响应完成后再出队下一个privatevoidTryProcessQueue(){lock(processLock){if(isProcessing)return;if(requestQueue.IsEmpty)return;if(requestQueue.TryDequeue(outvaritem)){currentClientitem;isProcessingtrue;serialPort.Write(item.Data,0,item.Data.Length);}}}4.3 网口 ↔ 串口协议转换以上这三个服务器项目的本质都是协议网关把以太网(TCP/UDP)上收到的 Modbus RTU 帧透传给串口设备再把串口返回的帧回发给发起请求的网络客户端。4.4 Modbus RTU 帧解析按功能码确定帧长度从Listbyte缓冲区中切片取完整帧功能码0x03读帧长 3 字节数 2(CRC)功能码0x06写固定 8 字节帧尾 2 字节 CRC16CRCHelper.CRC16完整帧解析实现以串口数据接收为例privatevoidSerialPort_DataReceived(objectsender,SerialDataReceivedEventArgse){if(serialPortnull||!serialPort.IsOpen)return;// 读取串口缓冲区全部数据byte[]buffernewbyte[serialPort.BytesToRead];serialPort.Read(buffer,0,buffer.Length);list.AddRange(buffer);// 循环处理缓冲区中可能存在的多个完整帧while(list.Count5){// 根据功能码计算帧长度intfuncCodelist[1];intfullFrameLength0;if(funcCode0X03)// 读寄存器响应{intlenlist[2];// 字节数fullFrameLength3len2;// 地址 功能码 字节数 数据 CRC}elseif(funcCode0X06)// 写单寄存器响应{fullFrameLength8;// 固定 8 字节}// 缓冲区长度足够一个完整帧if(list.CountfullFrameLength){byte[]fullFramelist.Take(fullFrameLength).ToArray();list.RemoveRange(0,fullFrameLength);// 将完整帧回发给发起请求的客户端if(currentClient!nullcurrentClient.TcpClient!nullcurrentClient.TcpClient.Connected){NetworkStreamstreamcurrentClient.TcpClient.GetStream();awaitstream.WriteAsync(fullFrame);}}elsebreak;// 数据不足等待更多字节}}4.5 连接状态与生命周期管理接受端AcceptTcpClientAsync返回的TcpClient用Connected判断活性ReadAsync返回0视为断开。停止统一先cts.Cancel()取消后台任务再Close()/Stop()/Dispose()释放网络与串口资源并把对象置null。客户端发送用lock保护NetworkStream.Write避免定时器与按钮并发发送互相踩踏。五、关键方法/属性速查表类方法/属性用途出现子项目TcpListenerStart()/Stop()启停监听TCPListen、TCPListen连接设备服务器TcpListenerPending()是否有挂起连接TCPListen、TCPListen连接设备服务器TcpListenerAcceptTcpClientAsync(CancellationToken)异步接受连接同上TcpClientConnectAsync(host, port)异步连接服务器TCPClient、TCPClientTest、TCPClient连接设备客户端TcpClientConnected/Available连接状态 / 可读字节全部 TCP 客户端TcpClientGetStream()获取 NetworkStream全部 TCPTcpClientClose()关闭连接全部 TCPNetworkStreamReadAsync(buf, token)异步读返回 0断开全部 TCPNetworkStreamWrite(buf)/WriteAsync(buf)同步/异步写全部 TCPUdpClientnew UdpClient(IPEndPoint)绑定本地端点WindowsFormsApp5/6UdpClientSend(buf, len, IPEndPoint)发送到指定端点WindowsFormsApp5/6UdpClientReceiveAsync()异步接收含来源端点WindowsFormsApp5/6UdpClientClose()/Dispose()释放资源WindowsFormsApp5/6六、对比与要点6.1 TCP vs UDP维度TCPTcpListener / TcpClientUDPUdpClient连接面向连接需Accept/Connect无连接直接Send/Receive可靠性可靠传输、保序不可靠、可能丢包/乱序服务器区分TcpListener监听 TcpClient表示每个连接仅UdpClient靠RemoteEndPoint区分客户端数据流NetworkStream读写流数据报Send/ReceiveAsync适用需要稳定可靠的设备控制Modbus TCP简单查询/广播/低开销场景6.2 同步 vs 异步项目统一采用异步 APIXxxAsyncawait配合CancellationToken实现可控停止避免阻塞 WinForms UI 线程。Pending()continue是一种轻量的非阻塞轮询写法但更推荐直接await AcceptTcpClientAsync(cts.Token)。6.3 .NET 9 vs .NET Framework 4.8 差异.NET 9项目date87 下 TCP 系列可使用AcceptTcpClientAsync(CancellationToken)、ReadAsync(buffer, token)等带取消令牌的重载。.NET Framework 4.8项目date84 下 UDP 系列使用ReceiveAsync()无取消令牌重载停止时靠cts循环判断 Close()触发异常退出循环。七、学习要点清单服务器三步走new TcpListener(ip, port)→Start()→AcceptTcpClientAsync()。客户端两步走new TcpClient()→ConnectAsync(host, port)再用GetStream()读写。ReadAsync返回0是判断对端正常关闭的关键信号。Available属性可用于接收循环中避免空转但异步ReadAsync本身会阻塞至有数据二者择一即可。UDP 服务器与客户端本质相同区别仅在绑定端点是否固定、是否主动Send。串口 网口混合场景下务必用队列 锁串行化串口访问。停止流程要有序Cancel()取消任务 →Close()/Stop()关闭资源 → 置null。Modbus RTU 帧需按功能码计算帧长并校验 CRC16TCP 承载时帧边界由ReadAsync返回长度保证UDP 则由数据报天然保界。

相关新闻

2026服装行业ERP选型指南与实施策略

2026服装行业ERP选型指南与实施策略

1. 2026年服装行业ERP选型全景图当我在2023年参与某女装品牌的ERP系统迁移时,CIO曾说过:"选错ERP相当于给企业装上不合脚的鞋,不仅走不快,还会磨得血肉模糊。"这句话在服装行业尤为贴切——季节性波动大、SKU数量庞大、…

2026/8/11 6:32:11 阅读更多 →
Halcon与C#联合开发工业视觉检测框架实践

Halcon与C#联合开发工业视觉检测框架实践

1. Halcon与C#联合开发框架概述在工业视觉检测领域,Halcon作为老牌机器视觉库一直占据重要地位。我团队基于Halcon 12和C#开发了一套生产级视觉检测框架,经过三年迭代现已升级至2.0改进版。这个框架最大的特点是封装了Halcon核心算子与C#交互逻辑&#x…

2026/8/11 6:32:11 阅读更多 →
JavaScript模块化:从CommonJS到ES Module的演进与实践

JavaScript模块化:从CommonJS到ES Module的演进与实践

1. JavaScript模块化发展背景与核心痛点2009年Node.js的出现让JavaScript首次具备了服务端开发能力,随之而来的大规模代码管理需求催生了CommonJS规范。我在早期Node项目中最直观的感受是:当代码量超过3000行时,全局作用域污染和依赖管理混乱…

2026/8/11 6:31:10 阅读更多 →

最新新闻

从重复劳动到自动化服务:工程化思维如何解决开发者的效率困境

从重复劳动到自动化服务:工程化思维如何解决开发者的效率困境

最近在技术社区里,有个词被反复提起,不是某个新框架,也不是某个算法,而是一种状态——“想Jump了”。它可能出现在某个深夜调试的帖子下,也可能出现在一个复杂需求的技术评审会后。这个词背后,是一种普遍存…

2026/8/11 8:06:51 阅读更多 →
Redis 8.10.0 正式发布:紧凑哈希、批量导入、备份恢复、流与时序能力全面升级

Redis 8.10.0 正式发布:紧凑哈希、批量导入、备份恢复、流与时序能力全面升级

Redis 8.10.0 于 2026 年 8 月 10 日正式发布,这是 Redis Open Source 的 Redis 8.10 通用可用版本。 相比 Redis 8.8,Redis 8.10 带来了紧凑哈希、高吞吐批量插入、基于 TLS 对等证书的节点认证、列表多元素迁移、集合基数统计、节点侧备份恢复、流读取…

2026/8/11 8:06:51 阅读更多 →
2026类似OpenClaw的无风险平替有哪些?支持内网部署的私有化替代方案商推荐

2026类似OpenClaw的无风险平替有哪些?支持内网部署的私有化替代方案商推荐

摘要 读者收益:读完本文,您将清晰了解2026年OpenClaw等开源通用框架在企业落地中面临的安全不可控、权限难管控、部署运维成本高三大核心痛点;掌握选择内网私有化部署替代方案时的核心选型维度与避坑要点;并获得以“速X 综合智能体…

2026/8/11 8:06:51 阅读更多 →
QtScrcpy终极指南:三步实现电脑无线控制安卓手机

QtScrcpy终极指南:三步实现电脑无线控制安卓手机

QtScrcpy终极指南:三步实现电脑无线控制安卓手机 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy 还在为手机屏幕太小而烦恼吗?想要在大屏幕上操作手机应用却…

2026/8/11 8:06:51 阅读更多 →
亚马逊商品详情 API 有哪些接口?如何获取 ASIN 标题、图片、变体数据

亚马逊商品详情 API 有哪些接口?如何获取 ASIN 标题、图片、变体数据

1. Catalog Items API v2022-04-01【查全网任意 ASIN,竞品详情】用途:输入 ASIN,拉取亚马逊公共目录公开商品数据(标题、图片、类目、五点、价格、变体、BSR 排名、参数),无需拥有该商品店铺,选…

2026/8/11 8:06:51 阅读更多 →
Frida内存Dump技术:从Android SO文件提取到ELF修复实战

Frida内存Dump技术:从Android SO文件提取到ELF修复实战

1. 项目概述:为什么我们需要Dump内存中的SO文件? 在Android逆向工程和安全分析领域,SO(Shared Object,共享库)文件是核心目标之一。它通常由C/C编写,承载着应用的核心算法、加密逻辑、协议实现等…

2026/8/11 8:05:50 阅读更多 →

日新闻

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/v…

2026/8/11 0:00:02 阅读更多 →
前后端分离项目中控制台与接口工具数据差异排查指南

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析:控制台与Apifox的数据差异 最近在调试一个前后端分离项目时,遇到了一个典型问题:后端服务在本地开发环境控制台能正常输出查询数据,但通过Apifox测试时却返回空结果。这种"控制台有数据,接口工具…

2026/8/11 0:00:03 阅读更多 →
AI编程实战:从Claude Code踩坑到游戏开发入门

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友,尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友,都在问我同一个问题:“听说现在用Claude Code这种AI编程工具,小白也能做游戏了,是真的吗&#…

2026/8/11 0:00:03 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/11 1:08:05 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 1:08:05 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/11 1:08:05 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/10 17:07:33 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/11 1:08:06 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/10 17:07:33 阅读更多 →