如何获取本地局域网内的可用IP地址
命题:如何获取本地局域网内的可用IP地址?
从这个命题,可以看出这里要解释的概念,什么是局域网?详见(http://baike.baidu.com/view/788.htm)
当然,在这篇文章中我们是指我们可以有效ping通的IP地址。
思路1:
穷举:
假设我们知道我们的IP地址为192.168.1.1 /24,即子网掩码为255.255.255.0,那么通过匹配192.168.1.*,所有可ping通的IP地址都为我们当前可获知的IP地址。
这里有一点需要解释一下,就是这个地址要ping地通,就以经验来告诉我们,这是错的。因为很多时候很多计算机显然连接在一个HUB或者SWITCH上,但是根本无法ping通,仅仅只是因为它的计算机可能的安全性问题所致。
但我们考虑到我们要ping通的计算机才有意义,因此,这种思路也是一种方案。
事实上,后续的几种方案依然存在这个问题。
穷举的方案详见:http://heisetoufa.javaeye.com/blog/253099
思路2:
利用DOS命令net view:http://tech.sina.com.cn/s/2006-04-07/1446895256.shtml
事实上这里要引进一种在.NET程序中利用DOS命令来解决的方案。
首先下面的类用来解决传递DOS命令的方案(很简单):
namespace WinFormShowLocalIPs { using System; using System.Diagnostics; public static class DOS { public static void CMD( string commandNameOrFileName, string arguments, DataReceivedEventHandler callback) { try { Process process = new Process(); process.StartInfo.FileName = commandNameOrFileName; process.StartInfo.Arguments = arguments; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardInput = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.CreateNoWindow = true; process.OutputDataReceived += new DataReceivedEventHandler(callback); process.Start(); process.BeginOutputReadLine(); process.WaitForExit(); process.Close(); } catch (Exception ex) { throw new ArgumentException("启动DOS命令失败!", ex); } } } }
然后就是调用DOS命令,并解析运行DOS后返回值的步骤:
namespace WinFormShowLocalIPs { using System; using System.Net; using System.Diagnostics; using System.Threading; using System.Net.Sockets; public class DnsHelper { public void AsynGetAddresses(DataReceivedEventHandler receivedHostEntry) { ReceivedHostEntry = receivedHostEntry; DOS.CMD("net.exe", "view", process_OutputDataReceived); } private void process_OutputDataReceived(object sender, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data)) { if (e.Data.StartsWith("\\\\")) { try { string hostName = e.Data.Substring(2).TrimEnd(); ResolveState ioContext = new ResolveState(hostName); GetHostEntryFinished.Reset(); IAsyncResult result = Dns.BeginGetHostEntry(ioContext.HostName, new AsyncCallback(GetHostAddressesCallback), ioContext); if (GetHostEntryFinished.WaitOne()) { if (ReceivedHostEntry != null) { ReceivedHostEntry(ioContext, e); } } } catch { } } } } ManualResetEvent GetHostEntryFinished = new ManualResetEvent(false); void GetHostAddressesCallback(IAsyncResult ar) { ResolveState ioContext = (ResolveState)ar.AsyncState; try { ioContext.IPs = Dns.EndGetHostEntry(ar); } catch(SocketException se) { ioContext.HasError = true; ioContext.ErrorMessage = "GetHostEntry has error!"; ioContext.Error = se; } GetHostEntryFinished.Set(); } public class ResolveState { string hostName; IPHostEntry resolvedIPs; public ResolveState(string host) { hostName = host; } public IPHostEntry IPs { get { return resolvedIPs; } set { resolvedIPs = value; } } public string HostName { get { return hostName; } set { hostName = value; } } private bool hasError = false; public bool HasError { get { return hasError; } set { hasError = value; } } public string ErrorMessage { get; set; } public Exception Error { get; set; } } public DataReceivedEventHandler ReceivedHostEntry { get; set; } } }
然后就是界面调用的方案:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WinFormShowLocalIPs { using System.Diagnostics; using System.Net; using System.Threading; using System.DirectoryServices; using System.ComponentModel; public partial class Form1 : Form { public Form1() { InitializeComponent(); lbIps.Width = 200; } private StringBuilder sb = new StringBuilder("Result:\n"); private void btnShowIps_Click(object sender, EventArgs e) { Thread thread = new Thread(new ThreadStart( () => { try { DnsHelper d = new DnsHelper(); d.AsynGetAddresses(ReceivedHostEntry); SetLbIps(sb.ToString()); sb.Remove(0, sb.Length); } finally { InterfaceHelper.ShowWaitingEffect(false, null); } })); thread.Start(); InterfaceHelper.ShowWaitingEffect(true, (o, args) => { //AppendWaiting(args.Data); string welcome = "Please wait!"; if (args.Count == 1) { SetLbIps(welcome); AppendLbIps(string.Format("[{0}]", args.Count)); } else { StringBuilder waiting = new StringBuilder(); SetLbIps(welcome); AppendLbIps(string.Format("[{0}]", args.Count)); while (args.Count-- != 0) { waiting.Append("."); } AppendLbIps(waiting.ToString()); } }); } void ReceivedHostEntry(object sender, DataReceivedEventArgs e) { WinFormShowLocalIPs.DnsHelper.ResolveState state = sender as WinFormShowLocalIPs.DnsHelper.ResolveState; if (state != null && !state.HasError) { sb.AppendFormat("HostName:{0}\n", state.HostName); foreach (IPAddress ip in state.IPs.AddressList) { sb.AppendLine(ip.ToString()); } } else if (state != null && state.HasError) { //sb.AppendLine("----------error start----------"); //sb.AppendLine(state.HostName); //sb.AppendLine(state.ErrorMessage); //sb.AppendLine("-----------error end-----------"); } } delegate void SetAsyncCallBack(string text); void SetLbIps(string args) { if (lbIps.InvokeRequired) { SetAsyncCallBack d = new SetAsyncCallBack(SetLbIps); this.Invoke(d, new object[] { args }); } else { lbIps.Text = args; } } void AppendLbIps(string args) { if (lbIps.InvokeRequired) { SetAsyncCallBack d = new SetAsyncCallBack(AppendLbIps); this.Invoke(d, new object[] { args }); } else { lbIps.Text += args; } } } }
上面的方案中包含以下有用信息:
1、对Windows 窗体控件进行线程安全调用(http://msdn.microsoft.com/zh-cn/library/ms171728.aspx)
2、如何显示进度条(文本进度条),基于多线程以及线程切换。
思路3:
利用DirectoryEntry来完成任务。关于DirectoryEntry,请参考MSDN(http://msdn.microsoft.com/zh-cn/library/system.directoryservices.directoryentry.aspx)
private void btnShowIPs2_Click(object sender, EventArgs e) { Thread thread = new Thread(new ThreadStart( () => { try { DirectoryEntry root = new DirectoryEntry("WinNT:"); foreach (DirectoryEntry Domain in root.Children) { //枚举工作组或域 sb.AppendLine(Domain.Name); foreach (DirectoryEntry Computer in Domain.Children) { //枚举指定工作组或域的计算机 if (Computer.SchemaClassName.Equals("Computer")) { IPHostEntry ipHost; try { ipHost = Dns.GetHostEntry(Computer.Name); foreach (IPAddress ip in ipHost.AddressList) { sb.AppendFormat("{0}:", Computer.Name); sb.AppendLine(ip.ToString()); } } catch { } } } } SetLbIps(sb.ToString()); sb.Remove(0, sb.Length); } finally { InterfaceHelper.ShowWaitingEffect(false, null); } })); thread.Start(); InterfaceHelper.ShowWaitingEffect(true, (o, args) => { AppendLbIps(args.Data); }); }
关于InterfaceHelper类:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace WinFormShowLocalIPs { public class InterfaceHelper { static Thread waitingThread = null; static int waitingCount = 0; public static void ShowWaitingEffect(bool showSwitch, EventHandler<InfoEventArgs> showHandler) { if (showSwitch && showHandler == null) { throw new ArgumentNullException("The handler can not be null!"); } if (!showSwitch && waitingThread != null) { waitingThread.Abort(); waitingThread = null; waitingCount = 0; return; } showHandler(null, new InfoEventArgs("Please wait for a while.") { Count = waitingCount }); waitingThread = new Thread(new ThreadStart( () => { while (showSwitch) { ++waitingCount; showHandler(null, new InfoEventArgs(".") { Count = waitingCount }); Thread.Sleep(1000); } })); waitingThread.Start(); } public class InfoEventArgs : EventArgs { private string args = string.Empty; public InfoEventArgs() { } public InfoEventArgs(string args) { this.args = args; } public string Data { get { return args; } set { args = value; } } public int Count { get; set; } } } }
posted on 2009-06-14 04:23 volnet(可以叫我大V) 阅读(5551) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述