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