如何获取本地局域网内的可用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; }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值