A:增加PID单独信息获取;增加进程信息获取函数
This commit is contained in:
1 parent
d1ecd6b6e2
commit
095783ea61
4 files changed
+246
-21
No files matched your search
@@ -17,7 +17,7 @@ public sealed class ProcessCache
|
||||
var process = Process.GetProcessById(pid);
|
||||
return $"{pid}-{process.StartTime:yyyyMMddHHmmss}";
|
||||
}
|
||||
|
||||
|
||||
// 私有构造函数,禁止外部创建实例
|
||||
private ProcessCache()
|
||||
{
|
||||
@@ -27,14 +27,17 @@ public sealed class ProcessCache
|
||||
/// <summary>
|
||||
/// 缓存字典【给定初始量 1000 ,后期可根据需求调整,避免频繁扩容】
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, ProgramInfo> _cache = new(1000);
|
||||
private readonly Dictionary<string, CacheItem> _cache = new(1000);
|
||||
|
||||
// 设置缓存
|
||||
public void Set(string key, ProgramInfo value)
|
||||
{
|
||||
lock (_cache)
|
||||
{
|
||||
_cache[key] = value;
|
||||
_cache[key] = new CacheItem
|
||||
{
|
||||
Info = value
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +46,16 @@ public sealed class ProcessCache
|
||||
{
|
||||
lock (_cache)
|
||||
{
|
||||
return _cache.GetValueOrDefault(key);
|
||||
if (_cache.TryGetValue(key, out var item))
|
||||
{
|
||||
if ((DateTime.Now - item.TimeStamp).TotalMinutes < 2)
|
||||
return item.Info;
|
||||
|
||||
// 超时,移除
|
||||
_cache.Remove(key);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,9 +68,15 @@ public sealed class ProcessCache
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CacheItem
|
||||
{
|
||||
public required ProgramInfo Info { get; init; }
|
||||
public DateTime TimeStamp { get; init; } = DateTime.Now;
|
||||
}
|
||||
/*
|
||||
PID 重用问题:
|
||||
|
||||
|
||||
🧠 背景 recap:
|
||||
操作系统(如 Windows)中的每个连接通常可以获取一个 PID。
|
||||
但由于:
|
||||
@@ -77,5 +95,5 @@ public sealed class ProcessCache
|
||||
但 PID 对应的进程启动时间是 18:10
|
||||
→ 说明这个进程是后来启动的(PID 被重用了)
|
||||
→ ❌ 不应该关联这条连接
|
||||
|
||||
*/
|
||||
|
||||
*/
|
||||
@@ -14,6 +14,7 @@ using Common.Logger;
|
||||
using Common.Net.HttpConn;
|
||||
using Common.Net.Models;
|
||||
using Common.Net.WebSocketConn;
|
||||
using Common.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.Events;
|
||||
using Utils.ETW.Etw;
|
||||
@@ -135,11 +136,16 @@ public partial class App : System.Windows.Application
|
||||
// 订阅 websocket 关闭服务
|
||||
WebSocketManager.Instance.SubscribeConnectionClosed((args =>
|
||||
{
|
||||
if (args.Uuid != null) DispatchEngine.Instance.DeleteApplicationInfo(args.Uuid);
|
||||
if (args.Uuid != null)
|
||||
{
|
||||
DispatchEngine.Instance.DeleteApplicationInfo(args.Uuid);
|
||||
DispatchEngine.Instance.DeleteProcessInfo(args.Uuid);
|
||||
}
|
||||
}
|
||||
));
|
||||
// 开启 WebSocket 定时发送服务
|
||||
DispatchEngine.Instance.ApplicationInfoDistribute();
|
||||
DispatchEngine.Instance.ProcessInfoDistribute();
|
||||
|
||||
// 启动 http 服务
|
||||
Task.Run(() => { _ = StartHttpServer(); });
|
||||
@@ -174,8 +180,9 @@ public partial class App : System.Windows.Application
|
||||
server.Get("/api",
|
||||
async (context) => { await context.Response.WriteJsonAsync(new { message = "Hi!" }); });
|
||||
|
||||
// 订阅某信息
|
||||
server.Post("/api/subscribe", async (context) =>
|
||||
#region 软件信息订阅
|
||||
|
||||
server.Post("/api/subscribe-application", async (context) =>
|
||||
{
|
||||
// 正确的做法:只处理请求体数据
|
||||
if (string.IsNullOrEmpty(context.RequestBody))
|
||||
@@ -199,18 +206,27 @@ public partial class App : System.Windows.Application
|
||||
string? uuid = context.Request.Headers["uuid"];
|
||||
Log.Warning($"接收到的数据: {requestData}, 用户 Id: {uuid}");
|
||||
|
||||
var subscriptionInfo = JsonSerializer.Deserialize<SubscriptionInfo>(requestData);
|
||||
if (subscriptionInfo != null && !string.IsNullOrWhiteSpace(uuid))
|
||||
if (string.IsNullOrWhiteSpace(uuid))
|
||||
{
|
||||
if (AppConfig.ApplicationInfoSubscribe.Equals(subscriptionInfo.SubscriptionType))
|
||||
context.Response.StatusCode = 400;
|
||||
await context.Response.WriteJsonAsync(new ResponseModel<object>
|
||||
{
|
||||
DispatchEngine.Instance.AddApplicationInfo(uuid, new DispatchModel
|
||||
{
|
||||
Interval = subscriptionInfo.Interval
|
||||
});
|
||||
}
|
||||
Success = false,
|
||||
Message = $"用户 ID 丢失!",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var subscriptionInfo = JsonHelper.FromJson<SubscriptionInfo>(requestData);
|
||||
if (subscriptionInfo != null)
|
||||
{
|
||||
// 软件信息订阅
|
||||
DispatchEngine.Instance.AddApplicationInfo(uuid, new DispatchModel
|
||||
{
|
||||
Interval = subscriptionInfo.Interval
|
||||
});
|
||||
|
||||
|
||||
Log.Warning($"名称: {subscriptionInfo.SubscriptionType}");
|
||||
Log.Warning($"时间: {subscriptionInfo.Interval}");
|
||||
}
|
||||
}
|
||||
@@ -235,7 +251,81 @@ public partial class App : System.Windows.Application
|
||||
});
|
||||
});
|
||||
|
||||
// 取消订阅
|
||||
#endregion
|
||||
|
||||
#region 线程信息订阅
|
||||
|
||||
server.Post("/api/subscribe-process", async (context) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(context.RequestBody))
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
await context.Response.WriteJsonAsync(new ResponseModel<object>
|
||||
{
|
||||
Success = false,
|
||||
Message = "请求体不能为空",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析请求数据
|
||||
try
|
||||
{
|
||||
string requestData = context.RequestBody;
|
||||
|
||||
// 打印原始数据用于调试
|
||||
string? uuid = context.Request.Headers["uuid"];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(uuid))
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
await context.Response.WriteJsonAsync(new ResponseModel<object>
|
||||
{
|
||||
Success = false,
|
||||
Message = $"用户 ID 丢失!",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var subscriptionInfo = JsonHelper.FromJson<SubscriptionProcessInfo>(requestData);
|
||||
if (subscriptionInfo != null)
|
||||
{
|
||||
DispatchEngine.Instance.DeleteProcessInfo(uuid);
|
||||
DispatchEngine.Instance.AddProcessInfo(uuid, new ProcessDispatchModel
|
||||
{
|
||||
Interval = subscriptionInfo.Interval,
|
||||
ProcessIds = subscriptionInfo.ProcessIds
|
||||
});
|
||||
Log.Warning($"时间: {subscriptionInfo.Interval}");
|
||||
Log.Warning($"监视的 ID : {subscriptionInfo.ProcessIds}");
|
||||
}
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
await context.Response.WriteJsonAsync(new ResponseModel<object>
|
||||
{
|
||||
Success = false,
|
||||
Message = $"请求数据格式错误: {ex.Message}",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 返回响应 - 只序列化纯数据对象
|
||||
context.Response.StatusCode = 200;
|
||||
await context.Response.WriteJsonAsync(new ResponseModel<string>
|
||||
{
|
||||
Success = true,
|
||||
Data = "成功",
|
||||
Message = "订阅成功",
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 取消订阅
|
||||
|
||||
server.Post("/api/unsubscribe", async (context) =>
|
||||
{
|
||||
// 正确的做法:只处理请求体数据
|
||||
@@ -260,13 +350,19 @@ public partial class App : System.Windows.Application
|
||||
string? uuid = context.Request.Headers["uuid"];
|
||||
Log.Warning($"接收到的数据: {requestData}, 用户 Id: {uuid}");
|
||||
|
||||
var subscriptionInfo = JsonSerializer.Deserialize<SubscriptionInfo>(requestData);
|
||||
var subscriptionInfo = JsonHelper.FromJson<SubscriptionInfo>(requestData);
|
||||
if (subscriptionInfo != null && !string.IsNullOrWhiteSpace(uuid))
|
||||
{
|
||||
// 软件信息订阅
|
||||
if (AppConfig.ApplicationInfoSubscribe.Equals(subscriptionInfo.SubscriptionType))
|
||||
{
|
||||
DispatchEngine.Instance.DeleteApplicationInfo(uuid);
|
||||
}
|
||||
// 进程信息订阅
|
||||
else if (AppConfig.ProcessInfoSubscribe.Equals(subscriptionInfo.SubscriptionType))
|
||||
{
|
||||
DispatchEngine.Instance.DeleteProcessInfo(uuid);
|
||||
}
|
||||
|
||||
Log.Warning($"取消订阅的 名称: {subscriptionInfo.SubscriptionType}");
|
||||
}
|
||||
@@ -292,6 +388,7 @@ public partial class App : System.Windows.Application
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
// 启动服务器
|
||||
try
|
||||
|
||||
@@ -27,6 +27,87 @@ public class ProcessNetworkInfo
|
||||
public List<string> ActiveConnections { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进程信息
|
||||
/// </summary>
|
||||
public class ProcessType
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程名称
|
||||
/// </summary>
|
||||
public string ProcessName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进程ID
|
||||
/// </summary>
|
||||
public int ProcessId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动时间
|
||||
/// </summary>
|
||||
public DateTime StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否退出
|
||||
/// </summary>
|
||||
public bool HasExited { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退出时间
|
||||
/// </summary>
|
||||
public DateTime? ExitTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退出代码
|
||||
/// </summary>
|
||||
public int? ExitCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 占用内存
|
||||
/// </summary>
|
||||
public long UseMemory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 线程数
|
||||
/// </summary>
|
||||
public int ThreadCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主模块路径
|
||||
/// </summary>
|
||||
public string? MainModulePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动文件名
|
||||
/// </summary>
|
||||
public string? MainModuleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上行总量
|
||||
/// </summary>
|
||||
public long TotalUploaded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下行总量
|
||||
/// </summary>
|
||||
public long TotalDownloaded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上行速度
|
||||
/// </summary>
|
||||
public double UploadSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下行速度
|
||||
/// </summary>
|
||||
public double DownloadSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有连接
|
||||
/// </summary>
|
||||
public List<ConnectionInfo> Connections { get; set; } = new List<ConnectionInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接详细信息
|
||||
/// </summary>
|
||||
@@ -35,14 +116,17 @@ public class ConnectionInfo
|
||||
public string ConnectionKey { get; set; }
|
||||
public int ProcessId { get; set; }
|
||||
public ProtocolType Protocol { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 本地 终结点
|
||||
/// </summary>
|
||||
public IPEndPoint LocalEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标 终结点
|
||||
/// </summary>
|
||||
public IPEndPoint RemoteEndpoint { get; set; }
|
||||
|
||||
public ConnectionState State { get; set; }
|
||||
public TrafficDirection Direction { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
@@ -138,10 +222,12 @@ public class ConnectionSnapshot
|
||||
public int RemotePort { get; set; }
|
||||
public string RemoteDomain { get; set; }
|
||||
public string State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 方向
|
||||
/// </summary>
|
||||
public string Direction { get; set; }
|
||||
|
||||
public DateTime StartTime { get; set; }
|
||||
public TimeSpan Duration { get; set; }
|
||||
public long BytesSent { get; set; }
|
||||
|
||||
@@ -390,6 +390,30 @@ public sealed class GlobalNetworkMonitor
|
||||
return _applications.Values.ToList().Select(applicationInfo => applicationInfo.ProgramInfo).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定的 pid 连接
|
||||
/// </summary>
|
||||
public List<ConnectionInfo> GetAllConnection(List<int> processIds)
|
||||
{
|
||||
var connectionInfos = _connections.Values.ToList();
|
||||
var ansList = new List<ConnectionInfo>();
|
||||
foreach (var t in processIds)
|
||||
{
|
||||
var infos = GetConnection(t);
|
||||
|
||||
ansList.AddRange(infos);
|
||||
}
|
||||
|
||||
return ansList;
|
||||
}
|
||||
|
||||
public List<ConnectionInfo> GetConnection(int processIds)
|
||||
{
|
||||
var connectionInfos = _connections.Values.ToList();
|
||||
var infos = connectionInfos.FindAll(info => info.ProcessId == processIds);
|
||||
return infos;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有辅助方法
|
||||
|
||||
Reference in new issue
Block a user