feat: 新增ARP刷新函数,并且在每次clearData后执行一次刷新
This commit is contained in:
parent
0410d14d3a
commit
99dc7b52cc
|
@ -214,7 +214,7 @@ class Camera
|
||||||
public async ValueTask<Result<byte[]>> ReadFrame()
|
public async ValueTask<Result<byte[]>> ReadFrame()
|
||||||
{
|
{
|
||||||
// 只在第一次或出错时清除UDP缓冲区,避免每帧都清除造成延迟
|
// 只在第一次或出错时清除UDP缓冲区,避免每帧都清除造成延迟
|
||||||
// await MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
|
MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
|
||||||
|
|
||||||
logger.Trace($"Reading frame from camera {this.address}");
|
logger.Trace($"Reading frame from camera {this.address}");
|
||||||
|
|
||||||
|
@ -280,6 +280,8 @@ class Camera
|
||||||
/// <returns>配置结果</returns>
|
/// <returns>配置结果</returns>
|
||||||
public async ValueTask<Result<bool>> ConfigureRegisters(UInt16[][] registerTable, int? customDelayMs = null)
|
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);
|
var i2c = new Peripherals.I2cClient.I2c(this.address, this.port, this.taskID, this.timeout);
|
||||||
|
|
||||||
foreach (var cmd in registerTable)
|
foreach (var cmd in registerTable)
|
||||||
|
|
|
@ -484,6 +484,151 @@ public class UDPServer
|
||||||
// 清空队列的最有效方式是替换为新的队列
|
// 清空队列的最有效方式是替换为新的队列
|
||||||
udpData.TryUpdate(key, new ConcurrentQueue<UDPData>(), dataQueue);
|
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>
|
/// <summary>
|
||||||
|
|
Loading…
Reference in New Issue