feat: 新增ARP刷新函数,并且在每次clearData后执行一次刷新
This commit is contained in:
		@@ -214,7 +214,7 @@ class Camera
 | 
			
		||||
    public async ValueTask<Result<byte[]>> ReadFrame()
 | 
			
		||||
    {
 | 
			
		||||
        // 只在第一次或出错时清除UDP缓冲区,避免每帧都清除造成延迟
 | 
			
		||||
        // await MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
 | 
			
		||||
        logger.Trace($"Reading frame from camera {this.address}");
 | 
			
		||||
 | 
			
		||||
@@ -253,7 +253,7 @@ class Camera
 | 
			
		||||
    private async ValueTask<Result<byte>> ReadRegister(UInt16 registerAddr)
 | 
			
		||||
    {
 | 
			
		||||
        var i2c = new Peripherals.I2cClient.I2c(this.address, this.port, this.taskID, this.timeout);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 地址高低字节
 | 
			
		||||
        var addrBytes = new byte[2];
 | 
			
		||||
        addrBytes[0] = (byte)(registerAddr >> 8);
 | 
			
		||||
@@ -280,6 +280,8 @@ class Camera
 | 
			
		||||
    /// <returns>配置结果</returns>
 | 
			
		||||
    public async ValueTask<Result<bool>> ConfigureRegisters(UInt16[][] registerTable, int? customDelayMs = null)
 | 
			
		||||
    {
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
 | 
			
		||||
        var i2c = new Peripherals.I2cClient.I2c(this.address, this.port, this.taskID, this.timeout);
 | 
			
		||||
 | 
			
		||||
        foreach (var cmd in registerTable)
 | 
			
		||||
@@ -1302,20 +1304,20 @@ class Camera
 | 
			
		||||
                logger.Error($"读取自动对焦初始化状态失败: {readResult.Error}");
 | 
			
		||||
                return new(readResult.Error);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            logger.Trace($"自动对焦初始化状态检查, state=0x{readResult.Value:X2}");
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            if (readResult.Value == 0x70)
 | 
			
		||||
            {
 | 
			
		||||
                break; // 初始化完成
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            if (iteration == 1)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"自动对焦初始化状态检查超时!! state=0x{readResult.Value:X2}");
 | 
			
		||||
                return new(new Exception($"自动对焦初始化状态检查超时, state=0x{readResult.Value:X2}"));
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            await Task.Delay(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -484,6 +484,151 @@ public class UDPServer
 | 
			
		||||
            // 清空队列的最有效方式是替换为新的队列
 | 
			
		||||
            udpData.TryUpdate(key, new ConcurrentQueue<UDPData>(), dataQueue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 强制进行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;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            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 neigh del <ip> dev <interface> (优先使用 ip 命令)
 | 
			
		||||
                // 如果 ip 命令不可用,则使用 arp -d <ip>
 | 
			
		||||
                if (IsCommandAvailable("ip"))
 | 
			
		||||
                {
 | 
			
		||||
                    command = "ip";
 | 
			
		||||
                    arguments = $"neigh flush {ipAddr}";
 | 
			
		||||
                }
 | 
			
		||||
                else if (IsCommandAvailable("arp"))
 | 
			
		||||
                {
 | 
			
		||||
                    command = "arp";
 | 
			
		||||
                    arguments = $"-d {ipAddr}";
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    logger.Warn("Neither 'ip' nor 'arp' command is available for ARP cache flush");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                logger.Warn($"Unsupported operating system for ARP cache flush");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 异步执行命令,避免阻塞主线程
 | 
			
		||||
            Task.Run(() => ExecuteArpCommand(command, arguments, ipAddr));
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error($"Error during ARP cache flush for {ipAddr}: {ex.Message}");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <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>
 | 
			
		||||
    /// 执行ARP命令
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="command">命令</param>
 | 
			
		||||
    /// <param name="arguments">参数</param>
 | 
			
		||||
    /// <param name="ipAddr">IP地址</param>
 | 
			
		||||
    private void ExecuteArpCommand(string command, string arguments, string ipAddr)
 | 
			
		||||
    {
 | 
			
		||||
        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($"ARP cache flush successful for {ipAddr}");
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    logger.Warn($"ARP cache flush failed for {ipAddr}. Exit code: {process.ExitCode}, Error: {error}");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                process.Kill();
 | 
			
		||||
                logger.Warn($"ARP cache flush command timed out for {ipAddr}");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error($"Failed to execute ARP cache flush command for {ipAddr}: {ex.Message}");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user