feat: 简单实现静态arp设置
This commit is contained in:
@@ -585,242 +585,6 @@ public class UDPServer
|
||||
}
|
||||
}
|
||||
|
||||
// 强制进行ARP刷新,防止后续传输时造成影响
|
||||
// FlushArpEntry(ipAddr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跨平台ARP缓存刷新
|
||||
/// </summary>
|
||||
/// <param name="ipAddr">目标IP地址</param>
|
||||
private void FlushArpEntry(string ipAddr)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 验证IP地址格式
|
||||
if (!IPAddress.TryParse(ipAddr, out var _))
|
||||
{
|
||||
logger.Warn($"Invalid IP address format: {ipAddr}");
|
||||
return;
|
||||
}
|
||||
|
||||
ExecuteArpFlush(ipAddr);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"Error during ARP cache flush for {ipAddr}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用Ping类重新刷新ARP缓存
|
||||
/// </summary>
|
||||
/// <param name="ipAddr">目标IP地址</param>
|
||||
private async void RefreshArpWithPing(string ipAddr)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var ping = new Ping();
|
||||
var options = new PingOptions
|
||||
{
|
||||
DontFragment = true,
|
||||
Ttl = 32,
|
||||
};
|
||||
|
||||
// 创建32字节的数据包
|
||||
byte[] buffer = new byte[32];
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
buffer[i] = (byte)(i % 256);
|
||||
}
|
||||
|
||||
// 异步发送ping,100ms超时
|
||||
var reply = await ping.SendPingAsync(ipAddr, 100, buffer, options);
|
||||
|
||||
if (reply.Status == IPStatus.Success)
|
||||
{
|
||||
logger.Debug($"ARP cache refreshed successfully for {ipAddr} (RTT: {reply.RoundtripTime}ms)");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Ping to {ipAddr} failed with status: {reply.Status}, but ARP entry should still be updated");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"Error refreshing ARP with ping for {ipAddr}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行ARP刷新流程:先删除ARP条目,再用ping重新刷新
|
||||
/// </summary>
|
||||
/// <param name="ipAddr">目标IP地址</param>
|
||||
private void ExecuteArpFlush(string ipAddr)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 第一步:删除ARP条目
|
||||
bool deleteSuccess = DeleteArpEntry(ipAddr);
|
||||
|
||||
if (deleteSuccess)
|
||||
{
|
||||
logger.Debug($"ARP entry deleted successfully for {ipAddr}");
|
||||
|
||||
// 第二步:使用Ping类重新刷新ARP缓存
|
||||
RefreshArpWithPing(ipAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Failed to delete ARP entry for {ipAddr}, but continuing with ping refresh");
|
||||
// 即使删除失败,也尝试ping刷新
|
||||
RefreshArpWithPing(ipAddr);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"Failed to execute ARP flush for {ipAddr}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除ARP条目
|
||||
/// </summary>
|
||||
/// <param name="ipAddr">目标IP地址</param>
|
||||
/// <returns>是否成功删除</returns>
|
||||
private bool DeleteArpEntry(string ipAddr)
|
||||
{
|
||||
try
|
||||
{
|
||||
string command;
|
||||
string arguments;
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
// Windows: arp -d <ip>
|
||||
command = "arp";
|
||||
arguments = $"-d {ipAddr}";
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
{
|
||||
// Linux/macOS: 优先使用 ip 命令删除
|
||||
if (IsCommandAvailable("ip"))
|
||||
{
|
||||
command = "ip";
|
||||
arguments = $"neigh del {ipAddr}";
|
||||
}
|
||||
else if (IsCommandAvailable("arp"))
|
||||
{
|
||||
command = "arp";
|
||||
arguments = $"-d {ipAddr}";
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Neither 'ip' nor 'arp' command is available for ARP entry deletion");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Unsupported operating system for ARP entry deletion");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExecuteCommand(command, arguments, $"delete ARP entry for {ipAddr}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"Error deleting ARP entry for {ipAddr}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查系统命令是否可用
|
||||
/// </summary>
|
||||
/// <param name="command">命令名称</param>
|
||||
/// <returns>命令是否可用</returns>
|
||||
private bool IsCommandAvailable(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = new System.Diagnostics.Process
|
||||
{
|
||||
StartInfo = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = OperatingSystem.IsWindows() ? "where" : "which",
|
||||
Arguments = command,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
process.WaitForExit(1000); // 1秒超时
|
||||
return process.ExitCode == 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行系统命令
|
||||
/// </summary>
|
||||
/// <param name="command">命令</param>
|
||||
/// <param name="arguments">参数</param>
|
||||
/// <param name="operation">操作描述</param>
|
||||
/// <returns>是否成功执行</returns>
|
||||
private bool ExecuteCommand(string command, string arguments, string operation)
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = new System.Diagnostics.Process
|
||||
{
|
||||
StartInfo = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = command,
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
|
||||
// 设置超时时间,避免进程挂起
|
||||
if (process.WaitForExit(5000)) // 5秒超时
|
||||
{
|
||||
var output = process.StandardOutput.ReadToEnd();
|
||||
var error = process.StandardError.ReadToEnd();
|
||||
|
||||
if (process.ExitCode == 0)
|
||||
{
|
||||
logger.Debug($"Command executed successfully: {operation}");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"Command failed: {operation}. Exit code: {process.ExitCode}, Error: {error}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
process.Kill();
|
||||
logger.Warn($"Command timed out: {operation}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"Failed to execute command for {operation}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user