feat: 使用netsh指令设置arp

This commit is contained in:
alivender
2025-07-18 14:37:25 +08:00
parent 35bad4027d
commit ba79a2093b
5 changed files with 179 additions and 66 deletions

View File

@@ -1,4 +1,5 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authorization;
@@ -16,6 +17,8 @@ namespace server.Controllers;
public class DataController : ControllerBase
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
// 固定的实验板IP,端口,MAC地址
private const string BOARD_IP = "169.254.109.0";
/// <summary>
/// [TODO:description]
@@ -48,6 +51,53 @@ public class DataController : ControllerBase
public DateTime? BoardExpireTime { get; set; }
}
/// <summary>
/// 获取本机IP地址优先选择与实验板同网段的IP
/// </summary>
/// <returns>本机IP地址</returns>
private IPAddress GetLocalIPAddress()
{
try
{
var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray();
// 优先选择与实验板IP前三段相同的IP
var sameSegmentIP = System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
&& nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
.SelectMany(nic => nic.GetIPProperties().UnicastAddresses)
.Where(addr => addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
.Select(addr => addr.Address)
.FirstOrDefault(addr =>
{
var segments = addr.ToString().Split('.');
return segments.Length == 4 &&
segments[0] == boardIpSegments[0] &&
segments[1] == boardIpSegments[1] &&
segments[2] == boardIpSegments[2];
});
if (sameSegmentIP != null)
return sameSegmentIP;
// 如果没有找到同网段的IP返回第一个可用的IP
return System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
&& nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
.SelectMany(nic => nic.GetIPProperties().UnicastAddresses)
.Where(addr => addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
.Select(addr => addr.Address)
.FirstOrDefault() ?? IPAddress.Loopback;
}
catch (Exception ex)
{
logger.Error(ex, "获取本机IP地址失败");
return IPAddress.Loopback;
}
}
/// <summary>
/// 用户登录,获取 JWT 令牌
/// </summary>
@@ -228,7 +278,7 @@ public class DataController : ControllerBase
return NotFound("没有可用的实验板");
var boardInfo = boardOpt.Value;
if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr)))
if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString())))
{
logger.Error($"无法配置ARP实验板可能会无法连接");
}
@@ -296,7 +346,7 @@ public class DataController : ControllerBase
return NotFound("未找到对应的实验板");
var boardInfo = ret.Value.Value;
if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr)))
if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString())))
{
logger.Error($"无法配置ARP实验板可能会无法连接");
}

View File

@@ -119,46 +119,7 @@ public class NetConfigController : ControllerBase
/// <returns>网络接口名称</returns>
private string GetLocalNetworkInterface()
{
try
{
var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray();
// 优先选择与实验板IP前三段相同的网络接口
var sameSegmentInterface = System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
&& nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
.FirstOrDefault(nic =>
{
var ipAddresses = nic.GetIPProperties().UnicastAddresses
.Where(addr => addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
.Select(addr => addr.Address);
return ipAddresses.Any(addr =>
{
var segments = addr.ToString().Split('.');
return segments.Length == 4 &&
segments[0] == boardIpSegments[0] &&
segments[1] == boardIpSegments[1] &&
segments[2] == boardIpSegments[2];
});
});
if (sameSegmentInterface != null)
return sameSegmentInterface.Name;
// 如果没有找到同网段的接口,返回第一个可用的接口
return System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
&& nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
.FirstOrDefault()?.Name ?? "未知";
}
catch (Exception ex)
{
logger.Error(ex, "获取本机网络接口名称失败");
return "未知";
}
return GetLocalIPAddress().ToString();
}
/// <summary>
@@ -484,6 +445,50 @@ public class NetConfigController : ControllerBase
}
}
/// <summary>
/// 设置板卡MAC地址
/// </summary>
/// <param name="boardMac">板卡MAC地址格式AA:BB:CC:DD:EE:FF</param>
/// <returns>操作结果</returns>
[HttpPost("SetBoardMAC")]
[EnableCors("Users")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> SetBoardMAC(string boardMac)
{
if (string.IsNullOrWhiteSpace(boardMac))
return BadRequest("板卡MAC地址不能为空");
// 解析MAC地址
if (!TryParseMacAddress(boardMac, out var macBytes))
return BadRequest("MAC地址格式不正确请使用格式AA:BB:CC:DD:EE:FF");
try
{
if (!(await InitializeArpAsync()))
{
throw new Exception("无法配置ARP记录");
}
// 创建网络配置客户端
var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
var result = await netConfig.SetBoardMAC(macBytes);
if (!result.IsSuccessful)
{
logger.Error($"设置板卡MAC地址失败: {result.Error}");
return StatusCode(StatusCodes.Status500InternalServerError, $"设置失败: {result.Error}");
}
return Ok(result.Value);
}
catch (Exception ex)
{
logger.Error(ex, "设置板卡MAC地址时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, "设置失败,请稍后重试");
}
}
/// <summary>
/// 设置主机MAC地址
/// </summary>