日期 |
更新内容 |
版本 |
作者 |
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 |
ResponseTargetType【0.0.6】
字段名 |
数据类型 |
说明 |
TaskId |
int |
任务Id |
Type |
byte |
终端类型,0:Server,1:Client |
字段名 |
数据类型 |
说明 |
TaskId |
int |
任务Id |
ResponseUdpAddress【0.0.7】
字段名 |
数据类型 |
说明 |
TaskId |
int |
任务Id |
Ip |
string |
组播地址 |
Port |
int |
组播端口 |
RequestServiceInfo【0.0.7】
字段名 |
数据类型 |
说明 |
TaskId |
int |
任务Id |
ResponseServiceInfo【0.0.7】
字段名 |
数据类型 |
说明 |
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 |
最后更新时间 |
RequestProcessIDList【0.0.5】
字段名 |
数据类型 |
说明 |
TaskId |
int |
任务Id |
ResponseProcessIDList【0.0.5】
字段名 |
数据类型 |
说明 |
TaskId |
int |
任务Id |
IDList |
int[] |
进程ID数组,有顺序,更新进程实时数据包需要根据该数组查找进程、更新数据 |
RequestProcessList【0.0.1】
字段名 |
数据类型 |
说明 |
TaskId |
int |
任务Id |
ResponseProcessList【0.0.5】
字段名 |
数据类型 |
说明 |
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 |
更新进程一般数据列表 |
UpdateRealtimeProcessList【0.0.5】
字段名 |
数据类型 |
说明 |
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) |
UpdateGeneralProcessList【0.0.5】
字段名 |
数据类型 |
说明 |
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 |
快乐玩转技术 |
|
|