using System.Net;
using System.Net.NetworkInformation;
using XFEExtension.NetCore.DelegateExtension;
namespace XFEExtension.NetCore.WebExtension.LANDeviceDetector;
///
/// 局域网设备探测器
///
public class LanDeviceDetector
{
///
/// 找到设备
///
public event XFEEventHandler? DeviceFind;
///
/// 网络地址搜索的起始位置
///
public string IPStart { get; set; }
///
/// 每个设备检测超时
///
public int TimeOut { get; set; }
///
/// 是否正在检测
///
public bool IsDetecting { get; set; }
///
/// 已找到的设备
///
public List FindDevices { get; set; } = [];
///
/// 局域网设备探测器
///
/// 网络地址搜索起始位置,default默认为本机设备所在网络频段
/// 超时
public LanDeviceDetector(string iPStart = "default", int timeOut = 100)
{
if (iPStart == "default")
{
var localIPAddress = WebExtension.GetLocalIPAddress();
IPStart = localIPAddress is not null ? $"{string.Join(".", localIPAddress.ToString().Split('.')[..3])}.*" : "192.168.1.*";
}
else
{
IPStart = "192.168.1.*";
}
TimeOut = timeOut;
}
///
/// 开始探测设备
///
///
public async Task StartDetecting()
{
IsDetecting = true;
while (IsDetecting)
{
FindDevices.AddRange(await InnerDetect(reply =>
{
IPHostEntry? hostEntry = null;
try { hostEntry = Dns.GetHostEntry(reply.Address); } catch { }
var device = new LanDeviceImpl(reply.Address, hostEntry, hostEntry?.HostName);
if (FindDevices.Any(d => d.IPAddress.ToString() == reply.Address.ToString()))
return;
FindDevices.Add(device);
DeviceFind?.Invoke(device);
}));
}
}
///
/// 检测一次
///
///
public async Task> Detect() => await InnerDetect(reply =>
{
IPHostEntry? hostEntry = null;
try { hostEntry = Dns.GetHostEntry(reply.Address); } catch { }
DeviceFind?.Invoke(new LanDeviceImpl(reply.Address, hostEntry, hostEntry?.HostName));
});
///
/// 停止探测设备
///
public void Stop() => IsDetecting = false;
private async Task> InnerDetect(Action action)
{
var tasks = new List();
var findDevices = new List();
for (var i = 1; i < 256; i++)
{
var currentIndex = i;
tasks.Add(Task.Run(async () =>
{
var ipAddress = IPStart.Replace("*", currentIndex.ToString());
using var ping = new Ping();
var reply = await ping.SendPingAsync(ipAddress, TimeOut);
if (reply.Status == IPStatus.Success)
{
IPHostEntry? hostEntry = null;
try { hostEntry = await Dns.GetHostEntryAsync(ipAddress); } catch { }
findDevices.Add(new LanDeviceImpl(reply.Address, hostEntry, hostEntry?.HostName));
action.Invoke(reply);
}
}));
}
await Task.WhenAll(tasks);
return findDevices;
}
}