fix: 使用C#自带的ping来刷新arp

This commit is contained in:
SikongJueluo 2025-07-16 13:26:10 +08:00
parent 0cfbebf804
commit b08b86dbbe
No known key found for this signature in database
1 changed files with 129 additions and 17 deletions

View File

@ -1,5 +1,6 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Net; using System.Net;
using System.Net.NetworkInformation; // 添加这个引用
using System.Net.Sockets; using System.Net.Sockets;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
@ -216,6 +217,8 @@ public class UDPServer : IDisposable
if (udpData.TryGetValue(key, out var sortedList) && sortedList.Count > 0) if (udpData.TryGetValue(key, out var sortedList) && sortedList.Count > 0)
{ {
data = new List<UDPData>(sortedList.Values); data = new List<UDPData>(sortedList.Values);
// 输出数据
// PrintDataArray(data);
sortedList.Clear(); sortedList.Clear();
break; break;
} }
@ -436,6 +439,9 @@ public class UDPServer : IDisposable
} }
sortedList.Add(uniqueTime, data); sortedList.Add(uniqueTime, data);
// 输出单个数据
PrintData(data);
// 输出全部数据
// PrintAllData(); // PrintAllData();
} }
finally finally
@ -495,6 +501,19 @@ public class UDPServer : IDisposable
"; ";
} }
/// <summary>
/// 输出UDP Data数组到log中
/// </summary>
/// <param name="dataArray">UDP数据列表</param>
public void PrintDataArray(IEnumerable<UDPData> dataArray)
{
foreach (var data in dataArray)
{
logger.Debug(PrintData(data));
}
}
/// <summary> /// <summary>
/// 将所有数据输出到log中 /// 将所有数据输出到log中
/// </summary> /// </summary>
@ -561,6 +580,95 @@ public class UDPServer : IDisposable
return; return;
} }
// 异步执行ARP刷新避免阻塞主线程
Task.Run(() => 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);
}
// 异步发送ping100ms超时
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 async 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 command;
string arguments; string arguments;
@ -572,12 +680,11 @@ public class UDPServer : IDisposable
} }
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{ {
// Linux/macOS: ip neigh del <ip> dev <interface> (优先使用 ip 命令) // Linux/macOS: 优先使用 ip 命令删除
// 如果 ip 命令不可用,则使用 arp -d <ip>
if (IsCommandAvailable("ip")) if (IsCommandAvailable("ip"))
{ {
command = "ip"; command = "ip";
arguments = $"neigh flush {ipAddr}"; arguments = $"neigh del {ipAddr}";
} }
else if (IsCommandAvailable("arp")) else if (IsCommandAvailable("arp"))
{ {
@ -586,22 +693,22 @@ public class UDPServer : IDisposable
} }
else else
{ {
logger.Warn("Neither 'ip' nor 'arp' command is available for ARP cache flush"); logger.Warn("Neither 'ip' nor 'arp' command is available for ARP entry deletion");
return; return false;
} }
} }
else else
{ {
logger.Warn($"Unsupported operating system for ARP cache flush"); logger.Warn($"Unsupported operating system for ARP entry deletion");
return; return false;
} }
// 异步执行命令,避免阻塞主线程 return ExecuteCommand(command, arguments, $"delete ARP entry for {ipAddr}");
Task.Run(() => ExecuteArpCommand(command, arguments, ipAddr));
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.Error($"Error during ARP cache flush for {ipAddr}: {ex.Message}"); logger.Error($"Error deleting ARP entry for {ipAddr}: {ex.Message}");
return false;
} }
} }
@ -637,12 +744,13 @@ public class UDPServer : IDisposable
} }
/// <summary> /// <summary>
/// 执行ARP命令 /// 执行系统命令
/// </summary> /// </summary>
/// <param name="command">命令</param> /// <param name="command">命令</param>
/// <param name="arguments">参数</param> /// <param name="arguments">参数</param>
/// <param name="ipAddr">IP地址</param> /// <param name="operation">操作描述</param>
private void ExecuteArpCommand(string command, string arguments, string ipAddr) /// <returns>是否成功执行</returns>
private bool ExecuteCommand(string command, string arguments, string operation)
{ {
try try
{ {
@ -669,22 +777,26 @@ public class UDPServer : IDisposable
if (process.ExitCode == 0) if (process.ExitCode == 0)
{ {
logger.Debug($"ARP cache flush successful for {ipAddr}"); logger.Debug($"Command executed successfully: {operation}");
return true;
} }
else else
{ {
logger.Warn($"ARP cache flush failed for {ipAddr}. Exit code: {process.ExitCode}, Error: {error}"); logger.Warn($"Command failed: {operation}. Exit code: {process.ExitCode}, Error: {error}");
return false;
} }
} }
else else
{ {
process.Kill(); process.Kill();
logger.Warn($"ARP cache flush command timed out for {ipAddr}"); logger.Warn($"Command timed out: {operation}");
return false;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.Error($"Failed to execute ARP cache flush command for {ipAddr}: {ex.Message}"); logger.Error($"Failed to execute command for {operation}: {ex.Message}");
return false;
} }
} }