{"id":23062204,"url":"https://github.com/dotnet9/csharpsockettest","last_synced_at":"2025-07-31T06:13:33.755Z","repository":{"id":213626056,"uuid":"734544059","full_name":"dotnet9/CsharpSocketTest","owner":"dotnet9","description":"C# socket测试：对象二进制序列化研究、TCP/UDP网络传输、WPF\\AvaloniaUI ListView\\DataGrid大数据加载、刷新","archived":false,"fork":false,"pushed_at":"2025-03-04T08:40:36.000Z","size":2384,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-03T11:12:36.838Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dotnet9.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-22T00:52:16.000Z","updated_at":"2025-03-04T08:40:39.000Z","dependencies_parsed_at":"2024-06-09T09:26:23.490Z","dependency_job_id":"16444cc6-96d6-459c-84e9-87b532830405","html_url":"https://github.com/dotnet9/CsharpSocketTest","commit_stats":null,"previous_names":["dotnet9/csharpsockettest"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dotnet9/CsharpSocketTest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotnet9%2FCsharpSocketTest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotnet9%2FCsharpSocketTest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotnet9%2FCsharpSocketTest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotnet9%2FCsharpSocketTest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dotnet9","download_url":"https://codeload.github.com/dotnet9/CsharpSocketTest/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotnet9%2FCsharpSocketTest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267997183,"owners_count":24178251,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-16T03:25:04.216Z","updated_at":"2025-07-31T06:13:33.734Z","avatar_url":"https://github.com/dotnet9.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# C#百万对象序列化与网络传输实践\n\n| 日期       | 更新内容                                                     | 版本  | 作者         |\n| ---------- | ------------------------------------------------------------ | ----- | ------------ |\n| 2023-12-16 | 初建，添加网络对象定义                                       | 0.0.1 | 沙漠尽头的狼 |\n| 2023-12-24 | 修改数据类型，节约网络传输大小和减少数据包个数               | 0.0.2 | 沙漠尽头的狼 |\n| 2024-02-07 | 1）添加界面截图，2）添加AvaloniaUI分支，1个UDP包拆分2个      | 0.0.3 | 沙漠尽头的狼 |\n| 2024-02-08 | 完善进程状态                                                 | 0.0.4 | 沙漠尽头的狼 |\n| 2024-02-09 | 修改通信对象，优化发包效率：常更新字段直接读取byte[]，优化数据包组装效率 | 0.0.5 | 沙漠尽头的狼 |\n| 2024-02-25 | 添加终端类型查询命令                                         | 0.0.6 | 沙漠尽头的狼 |\n| 2024-02-26 | 添加Udp组播地址请求命令，客户端不需要手工配置                | 0.0.7 | 沙漠尽头的狼 |\n| 2024-07-09 | 数据包Header添加8个字节长度的Unix毫秒时间戳                | 0.0.8 | 沙漠尽头的狼 |\n\n[TOC]\n\n## 1. 背景\n\n完善文章《[C#百万对象序列化深度剖析：如何在网络传输中实现速度与体积的完美平衡 (dotnet9.com)](https://dotnet9.com/2023/12/deep-analysis-of-csharp-million-object-serialization-how-to-achieve-a-perfect-balance-between-speed-and-volume-in-network-transm)》，以客户端实时获取服务端进程信息为测试案例：\n\n1. 以操作系统进程信息作为传输数据扩展数个网络数据包，操作系统进程有：进程ID、进程名称、CPU利用率、内存使用率等。\n2. C/S两端使用Avalonia UI作为界面展示；\n3. 添加TCP通信，客户端通过命令方式向服务端请求数据，服务端可被动响应，也可主动推送，主动推送场景包括修改进程、进程结构变化（增加进程、删除进程）等；\n4. 添加UDP通信，服务端可组播数据，主要是常变数据，比如CPU利用率、内存使用率、电源使用情况等；\n5. Avalonia UI百万数据DataGrid加载、实时更新。\n\n## 2. 数据包【0.0.5】\n\n**数据包=头部+数据**\n\n### 2.1. 头部【0.0.7】\n\n| 字段名          | 数据类型 | 说明                               |\n| --------------- | -------- | ---------------------------------- |\n| PacketSize      | int      | 数据包总大小=头部大小+数据部分大小 |\n| SystemId        | long     | 系统Id                             |\n| `ObjectId`      | byte     | 对象Id                             |\n| `ObjectVersion` | byte     | 对象版本                           |\n| `UnixTimeMilliseconds` | long     | Unix毫秒时间戳                           |\n\n### 2.2. 数据部分【0.0.5】\n\n1. 统一编码为UTF-8。\n\n1. TCP数据包基本使用`MessagePack`对对象进行二进制压缩，理论上数据包会比常规二进制序列化小2/3左右。\n2. UDP包不使用任何压缩框架，对于大数字类型(int\\double)压缩反而让数据包体积更大，所以使用`BinnaryReader`、`BinnaryWriter`做序列化和反序列化。\n3. `string`|`List\u003cT\u003e`|`Dictionary\u003cT1,T2\u003e`等集合类型：前4字节用int表示数量，后面部分为实际数据byte[]。\n\n## 3. 网络对象定义\n\nTCP、UDP传输数据包定义。\n\n### 3.1. TCP数据包【0.0.7】\n\n| 对象Id | 对象版本 | 对象名                | 说明                                     |\n| ------ | -------- | --------------------- | ---------------------------------------- |\n| 1      | 1        | RequestTargetType     | 请求目标终端类型                         |\n| 2      | 1        | ResponseTargetType    | 响应目标终端类型                         |\n| 3      | 1        | RequestUdpAddress     | 请求Udp组播地址                          |\n| 4      | 1        | ResponseUdpAddress    | 响应Udp组播地址                          |\n| 5      | 1        | RequestServiceInfo    | 请求服务基本信息                         |\n| 6      | 1        | ResponseServiceInfo   | 响应请求服务基本信息                     |\n| 7      | 1        | RequestProcessIDList  | 请求进程ID列表                           |\n| 8      | 1        | ResponseProcessIDList | 响应请求进程ID列表，更新实时数据需要使用 |\n| 9      | 1        | RequestProcessList    | 请求进程详细信息列表                     |\n| 10     | 1        | ResponseProcessList   | 响应请求进程详细信息列表                 |\n| 11     | 1        | UpdateProcessList     | 更新进程详细信息列表                     |\n| 12     | 1        | ChangeProcessList     | 进程结构变化：增加、减少进程             |\n| 199    | 1        | Heartbeat             | TCP心跳包                                |\n\n#### RequestTargetType【0.0.6】\n\n| 字段名 | 数据类型 | 说明   |\n| ------ | -------- | ------ |\n| TaskId | int      | 任务Id |\n\n#### ResponseTargetType【0.0.6】\n\n| 字段名 | 数据类型 | 说明                           |\n| ------ | -------- | ------------------------------ |\n| TaskId | int      | 任务Id                         |\n| Type   | byte     | 终端类型，0：Server，1：Client |\n\n#### RequestUdpAddress【0.0.7】\n\n| 字段名 | 数据类型 | 说明   |\n| ------ | -------- | ------ |\n| TaskId | int      | 任务Id |\n\n#### ResponseUdpAddress【0.0.7】\n\n| 字段名 | 数据类型 | 说明     |\n| ------ | -------- | -------- |\n| TaskId | int      | 任务Id   |\n| Ip     | string   | 组播地址 |\n| Port   | int      | 组播端口 |\n\n#### RequestServiceInfo【0.0.7】\n\n| 字段名 | 数据类型 | 说明   |\n| ------ | -------- | ------ |\n| TaskId | int      | 任务Id |\n\n#### ResponseServiceInfo【0.0.7】\n\n| 字段名             | 数据类型 | 说明                                                         |\n| ------------------ | -------- | ------------------------------------------------------------ |\n| TaskId             | int      | 任务Id                                                       |\n| OS                 | string?  | 操作系统名称                                                 |\n| MemorySize         | byte     | 系统内存大小（单位GB）                                       |\n| ProcessorCount     | byte     | 处理器个数                                                   |\n| DiskSize           | short    | 硬盘总容量（单位GB）                                         |\n| NetworkBandwidth   | short    | 网络带宽（单位Mbps）                                         |\n| Ips                | string?  | 服务器IP地址，多个IP地址以，分隔                             |\n| TimestampStartYear | byte     | 通信对象时间戳起始年份，比如：23，表示2023年1月1号开始计算时间戳，后面的时间戳都以这个字段计算为准，精确到0.1s，即100ms，主要用于节约网络对象传输大小 |\n| LastUpdateTime     | uint     | 最后更新时间                                                 |\n\n#### RequestProcessIDList【0.0.5】\n\n| 字段名 | 数据类型 | 说明   |\n| ------ | -------- | ------ |\n| TaskId | int      | 任务Id |\n\n#### ResponseProcessIDList【0.0.5】\n\n| 字段名 | 数据类型 | 说明                                                         |\n| ------ | -------- | ------------------------------------------------------------ |\n| TaskId | int      | 任务Id                                                       |\n| IDList | int[]    | 进程ID数组，有顺序，更新进程实时数据包需要根据该数组查找进程、更新数据 |\n\n#### RequestProcessList【0.0.1】\n\n| 字段名 | 数据类型 | 说明   |\n| ------ | -------- | ------ |\n| TaskId | int      | 任务Id |\n\n#### ResponseProcessList【0.0.5】\n\n| 字段名    | 数据类型             | 说明       |\n| --------- | -------------------- | ---------- |\n| TaskId    | int                  | 任务Id     |\n| TotalSize | int                  | 总数据大小 |\n| PageSize  | int                  | 分页大小   |\n| PageCount | int                  | 总页数     |\n| PageIndex | int                  | 页索引     |\n| Processes | `List\u003cProcessItem\u003e?` | 进程列表   |\n\n#### ProcessItem【0.0.5】\n\n| 字段名          | 数据类型 | 说明                                                         |\n| --------------- | -------- | ------------------------------------------------------------ |\n| Pid             | int      | 进程ID                                                       |\n| Name            | string?  | 进程名称                                                     |\n| Type            | byte     | 进程类型，0：应用，1：后台进程                               |\n| ProcessStatus   | byte     | 进程状态，0：新建状态，1：就绪状态，2：运行状态，3：阻塞状态，4：终止状态 |\n| AlarmStatus     | byte     | 告警状态，没有特别意义，可组合位域状态，0：正常，1：超时，2：超限，切换用户 |\n| Publisher       | string?  | 发布者                                                       |\n| CommandLine     | string?  | 命令行                                                       |\n| Cpu             | short    | Cpu（所有内核的总处理利用率），最后一位表示小数位，比如253表示25.3% |\n| Memory          | short    | 内存（进程占用的物理内存），最后一位表示小数位，比如253表示25.3%，值可根据基本信息计算 |\n| Disk            | short    | 磁盘（所有物理驱动器的总利用率），最后一位表示小数位，比如253表示25.3%，值可根据基本信息计算 |\n| Network         | short    | 网络（当前主要网络上的网络利用率），最后一位表示小数位，比如253表示25.3%，值可根据基本信息计算 |\n| Gpu             | short    | Gpu(所有Gpu引擎的最高利用率)，最后一位表示小数位，比如253表示25.3 |\n| GpuEngine       | byte     | Gpu引擎，0：无，1：GPU 0 - 3D                                |\n| PowerUsage      | byte     | 电源使用情况（CPU、磁盘和GPU对功耗的影响），0：非常低，1：低，2：中，3：高，4：非常高 |\n| PowerUsageTrend | byte     | 电源使用情况趋势（一段时间内CPU、磁盘和GPU对功耗的影响），0：非常低，1：低，2：中，3：高，4：非常高 |\n| LastUpdateTime  | uint     | 上次更新时间                                                 |\n| UpdateTime      | uint     | 更新时间                                                     |\n\n#### UpdateProcessList【0.0.1】\n\n| 字段名    | 数据类型             | 说明     |\n| --------- | -------------------- | -------- |\n| Processes | `List\u003cProcessItem\u003e?` | 进程列表 |\n\n#### ChangeProcessList【0.0.1】\n\n| 字段名 | 数据类型 | 说明 |\n| ------ | -------- | ---- |\n|        |          |      |\n\n#### Heartbeat【0.0.1】\n\n| 字段名 | 数据类型 | 说明 |\n| ------ | -------- | ---- |\n|        |          |      |\n\n### 3.2. UDP数据包【0.0.5】\n\n| 对象Id | 对象版本 | 对象名                    | 说明                 |\n| ------ | -------- | ------------------------- | -------------------- |\n| 200    | 1        | UpdateRealtimeProcessList | 更新进程实时数据列表 |\n| 201    | 1        | UpdateGeneralProcessList  | 更新进程一般数据列表 |\n\n#### UpdateRealtimeProcessList【0.0.5】\n\n| 字段名    | 数据类型 | 说明                                                         |\n| --------- | -------- | ------------------------------------------------------------ |\n| TotalSize | int      | 总数据大小                                                   |\n| PageSize  | int      | 分页大小                                                     |\n| PageCount | int      | 总页数                                                       |\n| PageIndex | int      | 页索引，客户端根据收到的进程ID列表、详细信息列表为基础，取当前数据包开始进程索引到结束进程索引进行数据更新 |\n| Cpus      | byte[]   | 一个进程占2字节(short)                                       |\n| Memories  | byte[]   | 一个进程占2字节(short)                                       |\n| Disks     | byte[]   | 一个进程占2字节(short)                                       |\n| Networks  | byte[]   | 一个进程占2字节(short)                                       |\n\n#### UpdateGeneralProcessList【0.0.5】\n\n| 字段名          | 数据类型 | 说明                                                         |\n| --------------- | -------- | ------------------------------------------------------------ |\n| TotalSize       | int      | 总数据大小                                                   |\n| PageSize        | int      | 分页大小                                                     |\n| PageCount       | int      | 总页数                                                       |\n| PageIndex       | int      | 页索引，客户端根据收到的进程ID列表、详细信息列表为基础，取当前数据包开始进程索引到结束进程索引进行数据更新 |\n| ProcessStatuses | byte[]   | 进程状态，一个进程占1字节(byte)                              |\n| AlarmStatuses   | byte[]   | 告警状态，一个进程占1字节(byte)                              |\n| Gpus            | byte[]   | 一个进程占2字节(short)                                       |\n| GpuEngines      | byte[]   | 一个进程占1字节(byte)                                        |\n| PowerUsages     | byte[]   | 一个进程占1字节(byte)                                        |\n| PowerUsageTrend | byte[]   | 一个进程占1字节(byte)                                        |\n| UpdateTimes     | byte[]   | 一个进程占4字节(byte)                                        |\n\n### 3.3. 部分枚举定义\n\n```csharp\n/// \u003csummary\u003e\n///     进程类型\n/// \u003c/summary\u003e\npublic enum ProcessType\n{\n    [Description(\"应用\")] Application,\n    [Description(\"后台进程\")] BackgroundProcess\n}\n\n/// \u003csummary\u003e\n///     进程运行状态\n/// \u003c/summary\u003e\npublic enum ProcessStatus\n{\n    [Description(\"新建状态\")] New,\n    [Description(\"就绪状态\")] Ready,\n    [Description(\"运行状态\")] Running,\n    [Description(\"阻塞状态\")] Blocked,\n    [Description(\"终止状态\")] Terminated\n}\n\n/// \u003csummary\u003e\n///     GPU引擎\n/// \u003c/summary\u003e\npublic enum GpuEngine\n{\n    [Description(\"无\")] None,\n    [Description(\"GPU 0 - 3D\")] Gpu03D\n}\n\n/// \u003csummary\u003e\n///     电源使用情况\n/// \u003c/summary\u003e\npublic enum ProcessPowerUsage\n{\n    [Description(\"非常低\")] VeryLow,\n    [Description(\"低\")] Low,\n    [Description(\"中\")] Moderate,\n    [Description(\"高\")] High,\n    [Description(\"非常高\")] VeryHigh\n}\n\n/// \u003csummary\u003e\n///     进程告警状态（没有意义，只用于测试枚举位域使用）\n/// \u003c/summary\u003e\n[Flags]\npublic enum ProcessAlarmStatus\n{\n    [Description(\"正常\")] Normal = 0,\n    [Description(\"超时\")] Overtime = 1,\n    [Description(\"超限\")] OverLimit = 2,\n    [Description(\"切换用户\")] UserChanged = 4\n}\n```\n\n## 4. 效果\n\n服务端使用Avalonia UI开发：\n\n![](imgs/server.gif)\n\n客户端使用Avalonia UI开发：\n\n![](imgs/client.gif)\n\n## 5. 技术交流\n\n### 5.1. 技术网站：\n\n- Https://dotnet9.com\n- Https://codewf.com\n- https://dotnetchat.com\n\n### 5.2. 微信公众号\n\n| Dotnet9                                                    | 快乐玩转技术                                                 |\n| ---------------------------------------------------------- | ------------------------------------------------------------ |\n| ![Dotnet9](https://img1.dotnet9.com/site/wechatpublic.jpg) | ![快乐玩转技术](https://img1.dotnet9.com/site/wechatpublic1.jpg) |\n\n### 5.3. 赞助\n\n| 微信支付                                         | 支付宝                                        | QQ支付                                       |\n| ------------------------------------------------ | --------------------------------------------- | -------------------------------------------- |\n| ![](https://img1.dotnet9.com/pays/WeChatPay.jpg) | ![](https://img1.dotnet9.com/pays/AliPay.jpg) | ![](https://img1.dotnet9.com/pays/QQPay.jpg) |\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotnet9%2Fcsharpsockettest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdotnet9%2Fcsharpsockettest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotnet9%2Fcsharpsockettest/lists"}