A:基础实现 及调整

This commit is contained in:
jimmy committed 2025-06-07 11:21:41 +08:00
1 parent a6922cea36
commit 04e912a830
6 files changed
+54 -94

No files matched your search

+33 -10
View File
@@ -8,16 +8,14 @@ namespace Infrastructure.GlobalCaches;
/// </summary>
public sealed class ProcessCache
{
private static readonly Lazy<ProcessCache> _instance = new Lazy<ProcessCache>(() => new ProcessCache());
private static readonly Lazy<ProcessCache> _instance = new(() => new ProcessCache());
public static ProcessCache Instance => _instance.Value;
public record ProcessCacheKey(int Pid, DateTime StartTime);
public ProcessCacheKey GetProcessKey(int pid)
public static string GetProcessKey(int pid)
{
var process = Process.GetProcessById(pid);
return new ProcessCacheKey(pid, process.StartTime);
return $"{pid}-{process.StartTime:yyyyMMddHHmmss}";
}
// 私有构造函数,禁止外部创建实例
@@ -26,11 +24,13 @@ public sealed class ProcessCache
// 初始化缓存等操作
}
// 示例缓存字段
private readonly Dictionary<ProcessCacheKey, ProgramInfo> _cache = new Dictionary<ProcessCacheKey, ProgramInfo>();
/// <summary>
/// 缓存字典【给定初始量 1000 ,后期可根据需求调整,避免频繁扩容】
/// </summary>
private readonly Dictionary<string, ProgramInfo> _cache = new(1000);
// 设置缓存
public void Set(ProcessCacheKey key, ProgramInfo value)
public void Set(string key, ProgramInfo value)
{
lock (_cache)
{
@@ -39,7 +39,7 @@ public sealed class ProcessCache
}
// 获取缓存
public ProgramInfo? Get(ProcessCacheKey key)
public ProgramInfo? Get(string key)
{
lock (_cache)
{
@@ -48,7 +48,7 @@ public sealed class ProcessCache
}
// 移除缓存
public void Remove(ProcessCacheKey key)
public void Remove(string key)
{
lock (_cache)
{
@@ -56,3 +56,26 @@ public sealed class ProcessCache
}
}
}
/*
PID 重用问题:
🧠 背景 recap:
操作系统(如 Windows)中的每个连接通常可以获取一个 PID。
但由于:
进程退出后,PID 会被操作系统复用(可能很快)
某些连接(如 TIME_WAIT、CLOSE_WAIT)在进程退出后仍然保留一段时间
因此:不能仅仅根据 PID 匹配连接与进程。
✅ 解决方法:引入 进程启动时间 + 连接时间戳 双重判断
✅ 核心原则:
一个连接只能属于:连接开始时间 ≥ 进程启动时间 的进程
❗反面例子:
如果连接时间是 18:00
但 PID 对应的进程启动时间是 18:10
→ 说明这个进程是后来启动的(PID 被重用了)
→ ❌ 不应该关联这条连接
*/
+1
View File
@@ -14,6 +14,7 @@
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\Utils.ETW\Utils.ETW.csproj" />
<ProjectReference Include="..\WinDivertNet\WinDivertNet.csproj" />
</ItemGroup>
+5 -71
View File
@@ -1,5 +1,10 @@
using Utils.ETW.Models;
namespace Infrastructure.Models;
/// <summary>
/// 进程信息【软件信息】
/// </summary>
public class ProgramInfo
{
/// <summary>
@@ -82,74 +87,3 @@ public class ProgramInfo
/// </summary>
public string IconBase64 { get; set; } = "";
}
/// <summary>
/// 网络信息
/// </summary>
public class NetInfo
{
/// <summary>
/// 进程 ID
/// </summary>
public int Pid { get; set; }
/// <summary>
/// 线程 ID
/// </summary>
public int Tid { get; set; }
/// <summary>
/// 数据方向 "Send" / "Recv"
/// </summary>
public string Direction { get; set; }
/// <summary>
/// 初次一次活动事件
/// </summary>
public DateTime FirstSeen { get; set; }
/// <summary>
/// 最近一次活动事件
/// </summary>
public DateTime LastSeen { get; set; }
/// <summary>
/// 连接状态
/// </summary>
public int State { get; set; }
/// <summary>
/// 源 IP
/// </summary>
public string SourceIp { get; set; }
/// <summary>
/// 源端口
///</summary>
public int SourcePort { get; set; }
/// <summary>
/// 目标 IP
///</summary>
public string DestIp { get; set; }
/// <summary>
/// 目标端口
///</summary>
public int DestPort { get; set; }
/// <summary>
/// 协议 TCP / UDP
///</summary>
public string Protocol { get; set; }
/// <summary>
/// 发送字节数
/// </summary>
public long TotalSendBytes { get; set; }
/// <summary>
/// 接收字节数
/// </summary>
public long TotalReceiveBytes { get; set; }
}
+1 -1
View File
@@ -21,7 +21,7 @@ public static class IconHelper
IntPtr hIcon = ExtractIcon(IntPtr.Zero, exePath, 0);
if (hIcon == IntPtr.Zero) return "";
using Icon icon = Icon.FromHandle(hIcon);
using System.Drawing.Icon icon = Icon.FromHandle(hIcon);
using Bitmap bmp = icon.ToBitmap();
using MemoryStream ms = new MemoryStream();
// 保存为 PNG 格式
+11 -10
View File
@@ -1,5 +1,6 @@
using System.Net;
using System.Runtime.InteropServices;
using Common.Logger;
namespace Infrastructure.utils;
@@ -38,7 +39,7 @@ public static class NetUtils
{
if (TraceEventSession.IsElevated() == false)
{
Console.WriteLine("请以管理员身份运行此程序。");
Log.Information("请以管理员身份运行此程序。");
return;
}
@@ -48,35 +49,35 @@ public static class NetUtils
session.EnableKernelProvider(
KernelTraceEventParser.Keywords.NetworkTCPIP);
Console.WriteLine("监听网络事件中(按 Ctrl+C 停止)...");
Log.Information("监听网络事件中(按 Ctrl+C 停止)...");
session.Source.Kernel.TcpIpConnect += data =>
{
Console.WriteLine(
Log.Information(
$"[TCP Connect] PID={data.ProcessID} {data.saddr}:{data.sport} -> {data.daddr}:{data.dport}");
};
session.Source.Kernel.TcpIpDisconnect += data =>
{
Console.WriteLine(
Log.Information(
$"[TCP Disconnect] PID={data.ProcessID} {data.saddr}:{data.sport} -> {data.daddr}:{data.dport}");
};
session.Source.Kernel.TcpIpSend += data =>
{
Console.WriteLine(
Log.Information(
$"[TCP Send] PID={data.ProcessID} {data.saddr}:{data.sport} -> {data.daddr}:{data.dport}, Size={data.size} bytes");
};
session.Source.Kernel.TcpIpRecv += data =>
{
Console.WriteLine(
Log.Information(
$"[TCP Recv] PID={data.ProcessID} {data.saddr}:{data.sport} <- {data.daddr}:{data.dport}, Size={data.size} bytes");
};
session.Source.Kernel.UdpIpSend += data =>
{
Console.WriteLine(
Log.Information(
$"[UDP Send] PID={data.ProcessID} {data.saddr}:{data.sport} -> {data.daddr}:{data.dport}, Size={data.size} bytes");
};
session.Source.Kernel.UdpIpRecv += data =>
{
Console.WriteLine(
Log.Information(
$"[UDP Recv] PID={data.ProcessID} {data.saddr}:{data.sport} <- {data.daddr}:{data.dport}, Size={data.size} bytes");
};
session.Source.Process(); // 开始监听
@@ -108,7 +109,7 @@ public static class NetUtils
int localPort = ntohs((ushort)row.localPort);
int remotePort = ntohs((ushort)row.remotePort);
Console.WriteLine(
Log.Information(
$"PID: {row.owningPid}, {localIp}:{localPort} -> {remoteIp}:{remotePort}, State: {row.state}");
rowPtr = IntPtr.Add(rowPtr, Marshal.SizeOf<MIB_TCPROW_OWNER_PID>());
}
@@ -192,7 +193,7 @@ public static class NetUtils
IPAddress localIp = new IPAddress(row.localAddr);
int localPort = ntohs1((ushort)row.localPort);
Console.WriteLine($"PID: {row.owningPid}, UDP {localIp}:{localPort}");
Log.Information($"PID: {row.owningPid}, UDP {localIp}:{localPort}");
rowPtr = IntPtr.Add(rowPtr, Marshal.SizeOf<MIB_UDPROW_OWNER_PID>());
}
}
+3 -2
View File
@@ -1,5 +1,6 @@
using Common;
using Common.ExpandException;
using Common.Logger;
namespace Infrastructure.utils;
@@ -69,7 +70,7 @@ public static class SysInfoUtils
#region 检查缓存
var pck = new ProcessCache.ProcessCacheKey(pid, proc.StartTime);
var pck = ProcessCache.GetProcessKey(pid);
var programInfo = ProcessCache.Instance.Get(pck);
if (programInfo != null)
{
@@ -119,7 +120,7 @@ public static class SysInfoUtils
// 只捕获能遇见的异常
catch (ArgumentException ex)
{
Console.WriteLine($"获取进程信息失败:{ex.Message}");
Log.Information($"获取进程信息失败:{ex.Message}");
throw ExceptionEnum.ProcessGetException;
}
}