feat: 配置板子网络时,更新动态mac

This commit is contained in:
SikongJueluo 2025-07-31 16:33:19 +08:00
parent bafd06162c
commit 2adeca3b99
No known key found for this signature in database
7 changed files with 46 additions and 37 deletions

View File

@ -14,6 +14,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ArpLookup" Version="2.0.3" />
<PackageReference Include="DotNext" Version="5.23.0" /> <PackageReference Include="DotNext" Version="5.23.0" />
<PackageReference Include="DotNext.Threading" Version="5.23.0" /> <PackageReference Include="DotNext.Threading" Version="5.23.0" />
<PackageReference Include="Honoo.IO.Hashing.Crc" Version="1.3.3" /> <PackageReference Include="Honoo.IO.Hashing.Crc" Version="1.3.3" />

View File

@ -1,11 +1,14 @@
using System.Diagnostics; using System.Diagnostics;
using System.Net.NetworkInformation;
using ArpLookup;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
/// <summary> /// <summary>
/// ARP 记录管理静态类(跨平台支持) /// ARP 记录管理静态类(跨平台支持)
/// </summary> /// </summary>
public static class Arp public static class ArpClient
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
@ -44,20 +47,28 @@ public static class Arp
} }
/// <summary> /// <summary>
/// 通过 Ping 动态更新指定 IP 的 ARP 记录 /// 动态更新指定 IP 的 ARP 记录
/// </summary> /// </summary>
/// <param name="ipAddress">要更新的 IP 地址</param> /// <param name="ipAddress">要更新的 IP 地址</param>
/// <returns>是否成功发送 Ping</returns> /// <returns>是否成功发送 Ping</returns>
public static async Task<bool> UpdateArpEntryByPingAsync(string ipAddress) public static async Task<bool> UpdateArpEntryAsync(string ipAddress)
{ {
if (string.IsNullOrWhiteSpace(ipAddress)) if (string.IsNullOrWhiteSpace(ipAddress))
throw new ArgumentException("IP 地址不能为空", nameof(ipAddress)); throw new ArgumentException("IP 地址不能为空", nameof(ipAddress));
try try
{ {
using var ping = new System.Net.NetworkInformation.Ping(); var ret = await ArpClient.DeleteArpEntryAsync(ipAddress);
var reply = await ping.SendPingAsync(ipAddress, 100); if (!ret)
return reply.Status == System.Net.NetworkInformation.IPStatus.Success; {
logger.Error($"删除 ARP 记录失败: {ipAddress}");
}
PhysicalAddress? mac = await Arp.LookupAsync(IPAddress.Parse(ipAddress));
if (mac == null)
return false;
return true;
} }
catch catch
{ {
@ -228,22 +239,22 @@ public static class Arp
return null; return null;
var lines = result.Output.Split('\n', StringSplitOptions.RemoveEmptyEntries); var lines = result.Output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
// 匹配接口行格式: Interface: 172.6.1.5 --- 0xa // 匹配接口行格式: Interface: 172.6.1.5 --- 0xa
var interfacePattern = @"Interface:\s+(\d+\.\d+\.\d+\.\d+)\s+---\s+(0x[a-fA-F0-9]+)"; var interfacePattern = @"Interface:\s+(\d+\.\d+\.\d+\.\d+)\s+---\s+(0x[a-fA-F0-9]+)";
var match = Regex.Match(line, interfacePattern); var match = Regex.Match(line, interfacePattern);
if (match.Success && match.Groups[1].Value == interfaceIp) if (match.Success && match.Groups[1].Value == interfaceIp)
{ {
// 将十六进制索引转换为十进制 // 将十六进制索引转换为十进制
var hexIndex = match.Groups[2].Value; var hexIndex = match.Groups[2].Value;
// 去掉 "0x" 前缀 // 去掉 "0x" 前缀
var hexValue = hexIndex.StartsWith("0x", StringComparison.OrdinalIgnoreCase) var hexValue = hexIndex.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
? hexIndex.Substring(2) ? hexIndex.Substring(2)
: hexIndex; : hexIndex;
if (int.TryParse(hexValue, System.Globalization.NumberStyles.HexNumber, null, out int decimalIndex)) if (int.TryParse(hexValue, System.Globalization.NumberStyles.HexNumber, null, out int decimalIndex))
{ {
logger.Debug($"找到接口 {interfaceIp} 的索引: {hexIndex} -> {decimalIndex}"); logger.Debug($"找到接口 {interfaceIp} 的索引: {hexIndex} -> {decimalIndex}");
@ -251,7 +262,7 @@ public static class Arp
} }
} }
} }
logger.Warn($"未找到接口 {interfaceIp} 的索引"); logger.Warn($"未找到接口 {interfaceIp} 的索引");
return null; return null;
} }
@ -417,9 +428,9 @@ public static class Arp
private static ArpEntry? ParseWindowsArpEntry(string line) private static ArpEntry? ParseWindowsArpEntry(string line)
{ {
// 跳过空行和标题行 // 跳过空行和标题行
if (string.IsNullOrWhiteSpace(line) || if (string.IsNullOrWhiteSpace(line) ||
line.Contains("Interface:") || line.Contains("Interface:") ||
line.Contains("Internet Address") || line.Contains("Internet Address") ||
line.Contains("Physical Address") || line.Contains("Physical Address") ||
line.Contains("Type")) line.Contains("Type"))
{ {
@ -518,7 +529,7 @@ public static class Arp
// 格式化 MAC 地址以适配不同操作系统 // 格式化 MAC 地址以适配不同操作系统
string formattedMac = FormatMacAddress(macAddress); string formattedMac = FormatMacAddress(macAddress);
var entry = await GetArpEntryAsync(ipAddress); var entry = await GetArpEntryAsync(ipAddress);
if (entry != null && string.Equals(FormatMacAddress(entry.MacAddress), formattedMac, StringComparison.OrdinalIgnoreCase)) if (entry != null && string.Equals(FormatMacAddress(entry.MacAddress), formattedMac, StringComparison.OrdinalIgnoreCase))
{ {
@ -534,7 +545,7 @@ public static class Arp
// 新增 ARP 记录 // 新增 ARP 记录
var ret = await AddArpEntryAsync(ipAddress, formattedMac, interfaceName); var ret = await AddArpEntryAsync(ipAddress, formattedMac, interfaceName);
if(!ret) logger.Error($"添加 ARP 记录失败: {ipAddress} -> {formattedMac} on {interfaceName}"); if (!ret) logger.Error($"添加 ARP 记录失败: {ipAddress} -> {formattedMac} on {interfaceName}");
return true; return true;
} }

View File

@ -51,7 +51,7 @@ public class DataController : ControllerBase
public DateTime? BoardExpireTime { get; set; } public DateTime? BoardExpireTime { get; set; }
} }
/// <summary> /// <summary>
/// 获取本机IP地址优先选择与实验板同网段的IP /// 获取本机IP地址优先选择与实验板同网段的IP
/// </summary> /// </summary>
/// <returns>本机IP地址</returns> /// <returns>本机IP地址</returns>
@ -60,7 +60,7 @@ public class DataController : ControllerBase
try try
{ {
var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray(); var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray();
// 优先选择与实验板IP前三段相同的IP // 优先选择与实验板IP前三段相同的IP
var sameSegmentIP = System.Net.NetworkInformation.NetworkInterface var sameSegmentIP = System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces() .GetAllNetworkInterfaces()
@ -278,7 +278,7 @@ public class DataController : ControllerBase
return NotFound("没有可用的实验板"); return NotFound("没有可用的实验板");
var boardInfo = boardOpt.Value; var boardInfo = boardOpt.Value;
if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString()))) if (!(await ArpClient.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString())))
{ {
logger.Error($"无法配置ARP实验板可能会无法连接"); logger.Error($"无法配置ARP实验板可能会无法连接");
} }
@ -346,7 +346,7 @@ public class DataController : ControllerBase
return NotFound("未找到对应的实验板"); return NotFound("未找到对应的实验板");
var boardInfo = ret.Value.Value; var boardInfo = ret.Value.Value;
if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString()))) if (!(await ArpClient.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString())))
{ {
logger.Error($"无法配置ARP实验板可能会无法连接"); logger.Error($"无法配置ARP实验板可能会无法连接");
} }
@ -490,4 +490,3 @@ public class DataController : ControllerBase
} }
} }
} }

View File

@ -380,7 +380,7 @@ public class DebuggerController : ControllerBase
} }
var rawData = dataResult.Value; var rawData = dataResult.Value;
logger.Debug($"rawData: {BitConverter.ToString(rawData)}"); // logger.Debug($"rawData: {BitConverter.ToString(rawData)}");
int depth = (int)config.captureDepth; int depth = (int)config.captureDepth;
int portDataLen = 4 * depth; int portDataLen = 4 * depth;
int portNum = (int)config.totalPortNum; int portNum = (int)config.totalPortNum;
@ -413,8 +413,7 @@ public class DebuggerController : ControllerBase
} }
var channelBytes = new byte[4 * depth]; var channelBytes = new byte[4 * depth];
Buffer.BlockCopy(channelUintArr, 0, channelBytes, 0, channelBytes.Length); Buffer.BlockCopy(channelUintArr, 0, channelBytes, 0, channelBytes.Length);
channelBytes = Common.Number.ReverseBytes(channelBytes, 4).Value; // logger.Debug($"{channel.name} HexData: {BitConverter.ToString(channelBytes)}");
logger.Debug($"{channel.name} HexData: {BitConverter.ToString(channelBytes)}");
var base64 = Convert.ToBase64String(channelBytes); var base64 = Convert.ToBase64String(channelBytes);
channelDataList.Add(new ChannelCaptureData { name = channel.name, data = base64 }); channelDataList.Add(new ChannelCaptureData { name = channel.name, data = base64 });
} }

View File

@ -19,8 +19,7 @@ public class NetConfigController : ControllerBase
// 固定的实验板IP,端口,MAC地址 // 固定的实验板IP,端口,MAC地址
private const string BOARD_IP = "169.254.109.0"; private const string BOARD_IP = "169.254.109.0";
private const int BOARD_PORT = 1234; private const int BOARD_PORT = 1234;
private const string BOARD_MAC = "12:34:56:78:9a:bc";
// 本机网络信息 // 本机网络信息
private readonly IPAddress _localIP; private readonly IPAddress _localIP;
private readonly byte[] _localMAC; private readonly byte[] _localMAC;
@ -33,14 +32,14 @@ public class NetConfigController : ControllerBase
// 初始化本机IP地址 // 初始化本机IP地址
_localIP = GetLocalIPAddress(); _localIP = GetLocalIPAddress();
_localIPString = _localIP?.ToString() ?? "未知"; _localIPString = _localIP?.ToString() ?? "未知";
// 初始化本机MAC地址 // 初始化本机MAC地址
_localMAC = GetLocalMACAddress(); _localMAC = GetLocalMACAddress();
_localMACString = _localMAC != null ? BitConverter.ToString(_localMAC).Replace("-", ":") : "未知"; _localMACString = _localMAC != null ? BitConverter.ToString(_localMAC).Replace("-", ":") : "未知";
// 获取本机网络接口名称 // 获取本机网络接口名称
_localInterface = GetLocalNetworkInterface(); _localInterface = GetLocalNetworkInterface();
logger.Info($"NetConfigController 初始化完成 - 本机IP: {_localIPString}, 本机MAC: {_localMACString}, 接口: {_localInterface}"); logger.Info($"NetConfigController 初始化完成 - 本机IP: {_localIPString}, 本机MAC: {_localMACString}, 接口: {_localInterface}");
} }
@ -53,7 +52,7 @@ public class NetConfigController : ControllerBase
try try
{ {
var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray(); var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray();
// 优先选择与实验板IP前三段相同的IP // 优先选择与实验板IP前三段相同的IP
var sameSegmentIP = System.Net.NetworkInformation.NetworkInterface var sameSegmentIP = System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces() .GetAllNetworkInterfaces()
@ -130,7 +129,7 @@ public class NetConfigController : ControllerBase
{ {
try try
{ {
return await Arp.CheckOrAddAsync(BOARD_IP, BOARD_MAC, _localInterface); return await ArpClient.UpdateArpEntryAsync(BOARD_IP);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -23,7 +23,7 @@ public static class MsgBus
/// <returns>无</returns> /// <returns>无</returns>
public async static void Init() public async static void Init()
{ {
if (!Arp.IsAdministrator()) if (!ArpClient.IsAdministrator())
{ {
logger.Error($"非管理员运行ARP无法更新请用管理员权限运行"); logger.Error($"非管理员运行ARP无法更新请用管理员权限运行");
// throw new Exception($"非管理员运行ARP无法更新请用管理员权限运行"); // throw new Exception($"非管理员运行ARP无法更新请用管理员权限运行");

View File

@ -479,10 +479,10 @@ async function startCapture() {
const arr = []; const arr = [];
for (let i = 0; i < bin.length; i += 4) { for (let i = 0; i < bin.length; i += 4) {
arr.push( arr.push(
(bin.charCodeAt(i) << 24) | bin.charCodeAt(i) |
(bin.charCodeAt(i + 1) << 16) | (bin.charCodeAt(i + 1) << 8) |
(bin.charCodeAt(i + 2) << 8) | (bin.charCodeAt(i + 2) << 16) |
bin.charCodeAt(i + 3), (bin.charCodeAt(i + 3) << 24),
); );
} }
// //