日期 | 更新内容 | 版本 | 作者 |
---|---|---|---|
2023-12-16 | 初建,添加网络对象定义 | 0.0.1 | 沙漠尽头的狼 |
2023-12-24 | 修改数据类型,节约网络传输大小和减少数据包个数 | 0.0.2 | 沙漠尽头的狼 |
2024-02-07 | 1)添加界面截图,2)添加AvaloniaUI分支,1个UDP包拆分2个 | 0.0.3 | 沙漠尽头的狼 |
2024-02-08 | 完善进程状态 | 0.0.4 | 沙漠尽头的狼 |
2024-02-09 | 修改通信对象,优化发包效率:常更新字段直接读取byte[],优化数据包组装效率 | 0.0.5 | 沙漠尽头的狼 |
2024-02-25 | 添加终端类型查询命令 | 0.0.6 | 沙漠尽头的狼 |
2024-02-26 | 添加Udp组播地址请求命令,客户端不需要手工配置 | 0.0.7 | 沙漠尽头的狼 |
2024-07-09 | 数据包Header添加8个字节长度的Unix毫秒时间戳 | 0.0.8 | 沙漠尽头的狼 |
[TOC]
完善文章《C#百万对象序列化深度剖析:如何在网络传输中实现速度与体积的完美平衡 (dotnet9.com)》,以客户端实时获取服务端进程信息为测试案例:
- 以操作系统进程信息作为传输数据扩展数个网络数据包,操作系统进程有:进程ID、进程名称、CPU利用率、内存使用率等。
- C/S两端使用Avalonia UI作为界面展示;
- 添加TCP通信,客户端通过命令方式向服务端请求数据,服务端可被动响应,也可主动推送,主动推送场景包括修改进程、进程结构变化(增加进程、删除进程)等;
- 添加UDP通信,服务端可组播数据,主要是常变数据,比如CPU利用率、内存使用率、电源使用情况等;
- Avalonia UI百万数据DataGrid加载、实时更新。
数据包=头部+数据
字段名 | 数据类型 | 说明 |
---|---|---|
PacketSize | int | 数据包总大小=头部大小+数据部分大小 |
SystemId | long | 系统Id |
ObjectId |
byte | 对象Id |
ObjectVersion |
byte | 对象版本 |
UnixTimeMilliseconds |
long | Unix毫秒时间戳 |
-
统一编码为UTF-8。
-
TCP数据包基本使用
MessagePack
对对象进行二进制压缩,理论上数据包会比常规二进制序列化小2/3左右。 -
UDP包不使用任何压缩框架,对于大数字类型(int\double)压缩反而让数据包体积更大,所以使用
BinnaryReader
、BinnaryWriter
做序列化和反序列化。 -
string
|List<T>
|Dictionary<T1,T2>
等集合类型:前4字节用int表示数量,后面部分为实际数据byte[]。
TCP、UDP传输数据包定义。
对象Id | 对象版本 | 对象名 | 说明 |
---|---|---|---|
1 | 1 | RequestTargetType | 请求目标终端类型 |
2 | 1 | ResponseTargetType | 响应目标终端类型 |
3 | 1 | RequestUdpAddress | 请求Udp组播地址 |
4 | 1 | ResponseUdpAddress | 响应Udp组播地址 |
5 | 1 | RequestServiceInfo | 请求服务基本信息 |
6 | 1 | ResponseServiceInfo | 响应请求服务基本信息 |
7 | 1 | RequestProcessIDList | 请求进程ID列表 |
8 | 1 | ResponseProcessIDList | 响应请求进程ID列表,更新实时数据需要使用 |
9 | 1 | RequestProcessList | 请求进程详细信息列表 |
10 | 1 | ResponseProcessList | 响应请求进程详细信息列表 |
11 | 1 | UpdateProcessList | 更新进程详细信息列表 |
12 | 1 | ChangeProcessList | 进程结构变化:增加、减少进程 |
199 | 1 | Heartbeat | TCP心跳包 |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
Type | byte | 终端类型,0:Server,1:Client |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
Ip | string | 组播地址 |
Port | int | 组播端口 |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
OS | string? | 操作系统名称 |
MemorySize | byte | 系统内存大小(单位GB) |
ProcessorCount | byte | 处理器个数 |
DiskSize | short | 硬盘总容量(单位GB) |
NetworkBandwidth | short | 网络带宽(单位Mbps) |
Ips | string? | 服务器IP地址,多个IP地址以,分隔 |
TimestampStartYear | byte | 通信对象时间戳起始年份,比如:23,表示2023年1月1号开始计算时间戳,后面的时间戳都以这个字段计算为准,精确到0.1s,即100ms,主要用于节约网络对象传输大小 |
LastUpdateTime | uint | 最后更新时间 |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
IDList | int[] | 进程ID数组,有顺序,更新进程实时数据包需要根据该数组查找进程、更新数据 |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
字段名 | 数据类型 | 说明 |
---|---|---|
TaskId | int | 任务Id |
TotalSize | int | 总数据大小 |
PageSize | int | 分页大小 |
PageCount | int | 总页数 |
PageIndex | int | 页索引 |
Processes | List<ProcessItem>? |
进程列表 |
字段名 | 数据类型 | 说明 |
---|---|---|
Pid | int | 进程ID |
Name | string? | 进程名称 |
Type | byte | 进程类型,0:应用,1:后台进程 |
ProcessStatus | byte | 进程状态,0:新建状态,1:就绪状态,2:运行状态,3:阻塞状态,4:终止状态 |
AlarmStatus | byte | 告警状态,没有特别意义,可组合位域状态,0:正常,1:超时,2:超限,切换用户 |
Publisher | string? | 发布者 |
CommandLine | string? | 命令行 |
Cpu | short | Cpu(所有内核的总处理利用率),最后一位表示小数位,比如253表示25.3% |
Memory | short | 内存(进程占用的物理内存),最后一位表示小数位,比如253表示25.3%,值可根据基本信息计算 |
Disk | short | 磁盘(所有物理驱动器的总利用率),最后一位表示小数位,比如253表示25.3%,值可根据基本信息计算 |
Network | short | 网络(当前主要网络上的网络利用率),最后一位表示小数位,比如253表示25.3%,值可根据基本信息计算 |
Gpu | short | Gpu(所有Gpu引擎的最高利用率),最后一位表示小数位,比如253表示25.3 |
GpuEngine | byte | Gpu引擎,0:无,1:GPU 0 - 3D |
PowerUsage | byte | 电源使用情况(CPU、磁盘和GPU对功耗的影响),0:非常低,1:低,2:中,3:高,4:非常高 |
PowerUsageTrend | byte | 电源使用情况趋势(一段时间内CPU、磁盘和GPU对功耗的影响),0:非常低,1:低,2:中,3:高,4:非常高 |
LastUpdateTime | uint | 上次更新时间 |
UpdateTime | uint | 更新时间 |
字段名 | 数据类型 | 说明 |
---|---|---|
Processes | List<ProcessItem>? |
进程列表 |
字段名 | 数据类型 | 说明 |
---|---|---|
字段名 | 数据类型 | 说明 |
---|---|---|
对象Id | 对象版本 | 对象名 | 说明 |
---|---|---|---|
200 | 1 | UpdateRealtimeProcessList | 更新进程实时数据列表 |
201 | 1 | UpdateGeneralProcessList | 更新进程一般数据列表 |
字段名 | 数据类型 | 说明 |
---|---|---|
TotalSize | int | 总数据大小 |
PageSize | int | 分页大小 |
PageCount | int | 总页数 |
PageIndex | int | 页索引,客户端根据收到的进程ID列表、详细信息列表为基础,取当前数据包开始进程索引到结束进程索引进行数据更新 |
Cpus | byte[] | 一个进程占2字节(short) |
Memories | byte[] | 一个进程占2字节(short) |
Disks | byte[] | 一个进程占2字节(short) |
Networks | byte[] | 一个进程占2字节(short) |
字段名 | 数据类型 | 说明 |
---|---|---|
TotalSize | int | 总数据大小 |
PageSize | int | 分页大小 |
PageCount | int | 总页数 |
PageIndex | int | 页索引,客户端根据收到的进程ID列表、详细信息列表为基础,取当前数据包开始进程索引到结束进程索引进行数据更新 |
ProcessStatuses | byte[] | 进程状态,一个进程占1字节(byte) |
AlarmStatuses | byte[] | 告警状态,一个进程占1字节(byte) |
Gpus | byte[] | 一个进程占2字节(short) |
GpuEngines | byte[] | 一个进程占1字节(byte) |
PowerUsages | byte[] | 一个进程占1字节(byte) |
PowerUsageTrend | byte[] | 一个进程占1字节(byte) |
UpdateTimes | byte[] | 一个进程占4字节(byte) |
/// <summary>
/// 进程类型
/// </summary>
public enum ProcessType
{
[Description("应用")] Application,
[Description("后台进程")] BackgroundProcess
}
/// <summary>
/// 进程运行状态
/// </summary>
public enum ProcessStatus
{
[Description("新建状态")] New,
[Description("就绪状态")] Ready,
[Description("运行状态")] Running,
[Description("阻塞状态")] Blocked,
[Description("终止状态")] Terminated
}
/// <summary>
/// GPU引擎
/// </summary>
public enum GpuEngine
{
[Description("无")] None,
[Description("GPU 0 - 3D")] Gpu03D
}
/// <summary>
/// 电源使用情况
/// </summary>
public enum ProcessPowerUsage
{
[Description("非常低")] VeryLow,
[Description("低")] Low,
[Description("中")] Moderate,
[Description("高")] High,
[Description("非常高")] VeryHigh
}
/// <summary>
/// 进程告警状态(没有意义,只用于测试枚举位域使用)
/// </summary>
[Flags]
public enum ProcessAlarmStatus
{
[Description("正常")] Normal = 0,
[Description("超时")] Overtime = 1,
[Description("超限")] OverLimit = 2,
[Description("切换用户")] UserChanged = 4
}
服务端使用Avalonia UI开发:
客户端使用Avalonia UI开发:
Dotnet9 | 快乐玩转技术 |
---|---|
微信支付 | 支付宝 | QQ支付 |
---|---|---|