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; } }