一对多 TCP 服务器与客户端流量控制系统开发文档
1. 文档目的
本文档为作者自己的练习项目,本人是一名 C# 和 WPF 初学者,本文从创建解决方案开始,逐步完成一个仅在本机运行的“一台服务器、多台客户端”TCP 通信项目。
完成后,你可以先启动服务器,再多次启动客户端程序;每个客户端都能向服务器发送文本,服务器只把文本回显给原客户端。服务器与客户端均展示实时流量数据,且每个客户端的上传、下载流量均独立限速。
本文是第一版的完整范围。请严格按“实施顺序”逐步完成并验证,不要一开始同时编写所有文件。
ps:如有需要可向作者私聊无偿索要源码
2. 已确认的需求
| 开发语言与框架 | C#、.NET 8、WPF |
| 运行方式 | 仅本机模拟,不部署到局域网或互联网 |
| 通信协议 | TCP |
| 服务端形式 | 独立 WPF 程序 |
| 客户端形式 | 独立 WPF 程序,可多次打开 |
| 通信模式 | 一个服务器对应多个客户端 |
| 消息类型 | UTF-8 文本 |
| 服务器处理方式 | 只回显给发送消息的客户端 |
| 流量控制 | 每个客户端独立限制上传与下载速率 |
| 修改限速 | 不提供运行时界面修改;修改默认值后重启程序 |
| 数据展示 | 数值、进度条、表格、日志 |
| 折线图 | 不需要 |
| 自动发送 | 需要,用于制造流量并验证限速 |
| 不做的功能 | 文件传输、群发、登录、数据库、远程部署 |
3. 基本概念
本项目中“上传”和“下载”的方向固定如下:
客户端 -> 服务器:上传流量
服务器 -> 原客户端:下载流量(服务器回显)
服务器不是聊天服务器。客户端 A 发送的内容只会返回给 A,不会发送给 B、C 等其他客户端。
#mermaid-svg-LX676Ddf0zMqffdG{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LX676Ddf0zMqffdG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LX676Ddf0zMqffdG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LX676Ddf0zMqffdG .error-icon{fill:#552222;}#mermaid-svg-LX676Ddf0zMqffdG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LX676Ddf0zMqffdG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LX676Ddf0zMqffdG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LX676Ddf0zMqffdG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LX676Ddf0zMqffdG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LX676Ddf0zMqffdG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LX676Ddf0zMqffdG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LX676Ddf0zMqffdG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LX676Ddf0zMqffdG .marker.cross{stroke:#333333;}#mermaid-svg-LX676Ddf0zMqffdG svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LX676Ddf0zMqffdG p{margin:0;}#mermaid-svg-LX676Ddf0zMqffdG .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-LX676Ddf0zMqffdG .cluster-label text{fill:#333;}#mermaid-svg-LX676Ddf0zMqffdG .cluster-label span{color:#333;}#mermaid-svg-LX676Ddf0zMqffdG .cluster-label span p{background-color:transparent;}#mermaid-svg-LX676Ddf0zMqffdG .label text,#mermaid-svg-LX676Ddf0zMqffdG span{fill:#333;color:#333;}#mermaid-svg-LX676Ddf0zMqffdG .node rect,#mermaid-svg-LX676Ddf0zMqffdG .node circle,#mermaid-svg-LX676Ddf0zMqffdG .node ellipse,#mermaid-svg-LX676Ddf0zMqffdG .node polygon,#mermaid-svg-LX676Ddf0zMqffdG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LX676Ddf0zMqffdG .rough-node .label text,#mermaid-svg-LX676Ddf0zMqffdG .node .label text,#mermaid-svg-LX676Ddf0zMqffdG .image-shape .label,#mermaid-svg-LX676Ddf0zMqffdG .icon-shape .label{text-anchor:middle;}#mermaid-svg-LX676Ddf0zMqffdG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LX676Ddf0zMqffdG .rough-node .label,#mermaid-svg-LX676Ddf0zMqffdG .node .label,#mermaid-svg-LX676Ddf0zMqffdG .image-shape .label,#mermaid-svg-LX676Ddf0zMqffdG .icon-shape .label{text-align:center;}#mermaid-svg-LX676Ddf0zMqffdG .node.clickable{cursor:pointer;}#mermaid-svg-LX676Ddf0zMqffdG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LX676Ddf0zMqffdG .arrowheadPath{fill:#333333;}#mermaid-svg-LX676Ddf0zMqffdG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LX676Ddf0zMqffdG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LX676Ddf0zMqffdG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LX676Ddf0zMqffdG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LX676Ddf0zMqffdG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LX676Ddf0zMqffdG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LX676Ddf0zMqffdG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LX676Ddf0zMqffdG .cluster text{fill:#333;}#mermaid-svg-LX676Ddf0zMqffdG .cluster span{color:#333;}#mermaid-svg-LX676Ddf0zMqffdG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LX676Ddf0zMqffdG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LX676Ddf0zMqffdG rect.text{fill:none;stroke-width:0;}#mermaid-svg-LX676Ddf0zMqffdG .icon-shape,#mermaid-svg-LX676Ddf0zMqffdG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LX676Ddf0zMqffdG .icon-shape p,#mermaid-svg-LX676Ddf0zMqffdG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LX676Ddf0zMqffdG .icon-shape .label rect,#mermaid-svg-LX676Ddf0zMqffdG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LX676Ddf0zMqffdG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LX676Ddf0zMqffdG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LX676Ddf0zMqffdG :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}


