如何使用VB.Net获取局域网内的所有IP地址
问题分析与解决方案
核心问题
你的代码只显示最后一个IP的主要原因是IP地址拼接错误:直接将数字i追加到本地IP末尾(比如本地IP是192.168.1.1,拼接后变成192.168.1.11、192.168.1.12等),这并非正确的局域网IP段格式。此外,频繁在并行循环中跨线程更新UI也可能导致数据丢失或显示异常。
修复步骤
- 正确拼接局域网IP段:拆分本地IP的前三个网段,拼接成
xxx.xxx.xxx.i的格式(i从1到254)。 - 后台线程收集数据,批量更新UI:避免在并行循环中频繁调用
BeginInvoke,先在后台线程收集所有活跃设备信息,再一次性更新DataGridView。 - 优化Ping和DNS解析逻辑:在后台线程完成所有耗时操作,避免阻塞UI。
修改后的完整代码
Imports System.Net Imports System.Net.NetworkInformation Imports System.Net.Sockets Imports System.Threading Imports System.IO Imports System.Collections.Generic Public Class Form1 ' 定义存储设备信息的类 Private Class DeviceInfo Public Property IpAddress As String Public Property HostName As String Public Property Status As String End Class Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim strHost As String = Dns.GetHostName() ' 获取本地IPv4地址(避免取到IPv6) Dim strIp As String = Dns.GetHostEntry(strHost).AddressList.First(Function(ip) ip.AddressFamily = AddressFamily.InterNetwork).ToString() TxtForIp.Text = strIp End Sub Private Sub BgScanningForIps_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BgScanningForIps.DoWork Dim activeDevices As New List(Of DeviceInfo)() ' 拆分本地IP的前三个网段 Dim ipSegments As String() = TxtForIp.Text.Split("."c) If ipSegments.Length <> 4 Then MessageBox.Show("无效的IP地址格式") Return End If Dim baseIp As String = $"{ipSegments(0)}.{ipSegments(1)}.{ipSegments(2)}." ' 并行扫描1-254的IP Parallel.For(1, 255, Sub(i, loopState) Using ping As New Ping() Dim targetIp As String = baseIp & i.ToString() Try Dim pinRpl As PingReply = ping.Send(targetIp, 100) ' 设置超时时间,提升扫描速度 If pinRpl.Status = IPStatus.Success Then Dim hostName As String = "?" Try ' 在后台线程解析主机名,避免阻塞UI Dim host As IPHostEntry = Dns.GetHostEntry(targetIp) hostName = host.HostName Catch ' 解析失败时保持默认值 End Try ' 线程安全地添加到列表 SyncLock activeDevices activeDevices.Add(New DeviceInfo With { .IpAddress = targetIp, .HostName = hostName, .Status = "active" }) End SyncLock End If Catch ' 忽略Ping失败的情况 End Try End Using End Sub) ' 将收集到的设备信息传递给UI线程更新 e.Result = activeDevices End Sub ' 后台工作完成后更新UI Private Sub BgScanningForIps_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BgScanningForIps.RunWorkerCompleted If e.Error IsNot Nothing Then MessageBox.Show($"扫描出错: {e.Error.Message}") Return End If Dim activeDevices As List(Of DeviceInfo) = DirectCast(e.Result, List(Of DeviceInfo)) ' 清空原有数据 DataGridView1.Rows.Clear() ' 批量添加行 For Each device In activeDevices DataGridView1.Rows.Add(device.IpAddress, device.HostName, device.Status) Next MessageBox.Show("扫描完成") End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' 扫描前禁用按钮,防止重复触发 Button1.Enabled = False BgScanningForIps.RunWorkerAsync() End Sub End Class
关键改进点
- 正确的IP拼接:通过拆分本地IP获取基础网段,生成合法的局域网IP地址。
- 线程安全的数据收集:使用
SyncLock确保并行环境下列表操作的安全性。 - 批量UI更新:在后台线程完成所有扫描和解析后,一次性更新DataGridView,避免频繁跨线程操作导致的问题。
- 超时设置:Ping时设置100ms超时,大幅提升扫描速度。
- 错误处理:增加对无效IP、Ping失败、DNS解析失败的处理,提升代码健壮性。
内容的提问来源于stack exchange,提问作者Waqar Vickey
相关产品推荐
相关产品推荐

