前言
因为公司设备太多,偶尔遇到 IP 分配冲突问题,所以写了一个可视化的 GUI 小工具来快速排查掉已被占用的 IP 地址以及分析局域网概况,包括局域网主机延迟、在线状态、系统类型、主机名、Mac地址等。
成品展示
下载软件
文图介绍
通过设置要扫描的局域网 IP 段和起始结束数值即可开始扫描。
扫描后可以查看结果信息。
通过详细模式可以查看更多细节,以及分析局域网概况,包括局域网主机延迟、在线状态、系统类型、主机名、Mac地址等。
功能设想与实现
基础检测方案:
通过基础 Ping 功能对目标 IP 发出 ICMP 数据,以取得目标 IP 状态(是否在线、延迟)。
性能优化方案:
使用多线程+线程池方式调用检测,减小等待时间,提升运行效率。
代码逻辑
通过 C# 自带的 Net 实现基础 Ping 服务
1 2
| Ping ping = new Ping(); PingReply reply = ping.Send(ipAddress);
|
Ping 发送后,获取目标的状态信息。
1 2 3 4 5
| reply.Status
reply.RoundtripTime
|
至此一个基础的探测逻辑成功实现。
代码书写:
先创建一个实体类,用来存放状态信息。
1 2 3 4 5 6 7 8
| internal class StatusEntity { public string IPAddress { get; set; }
public bool IsOnline { get; set; }
public long Ms { get; set; } }
|
现在要结合多线程与遍历设置的局域网 IP 范围进行获取遍历后的状态信息结果。
1 2 3 4 5 6 7 8 9 10 11 12 13
| int startRange = 1; int endRange = 255;
for (int i = startRange; i <= endRange; i++) { string ipAddress = baseIpAddress + i.ToString(); Trace.WriteLine($"{ipAddress} | {baseIpAddress + i.ToString()}"); Thread thread = new Thread(() => PingHost(ipAddress)); thread.Start(); }
ThreadPool.QueueUserWorkItem(_ => WaitPingTestAllThreads());
|
PingHost() 为自封装方法,通过调用 PingHost(传入 IP 地址),然后将 Ping 结果存入 List 内。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| private BlockingCollection<StatusEntity> statusEntities = new BlockingCollection<StatusEntity>();
void PingHost(string ipAddress) { try { Ping ping = new Ping(); PingReply reply = ping.Send(ipAddress);
statusEntities.Add(new StatusEntity { IPAddress = ipAddress, IsOnline = reply.Status == IPStatus.Success, Ms = reply.RoundtripTime }); } catch (Exception ex) { Trace.WriteLine($"{ipAddress}: 请求错误,错误信息:{ex.Message}"); } }
|
将结果渲染成 UI 展示给用户。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| private void WaitPingTestAllThreads() { foreach (StatusEntity statusEntity in statusEntities) { this.Invoke(new Action(() => { Panel panel = new Panel(); panel.Width = 48; panel.Height = 48;
Label num = new Label(); num.AutoSize = false; num.Margin = new Padding(0); num.Width = width; num.Text = statusEntity.IPAddress
Label ms = new Label(); ms.AutoSize = false; ms.Margin = new Padding(0); ms.Width = width; ms.Text = statusEntity.Ms
panel.Controls.Add(num); panel.Controls.Add(ms);
Panel_Main.Controls.Add(panel); })); } }
|
后续更新方向
- 有些时候 Ping 可能也不能准确获取状态,比如防火墙拦截之类的。需要多个方案配合会更稳定。
- 增加更详细的 UI 状态显示。