<轉>用C#獲取局域網內所有機器


如果你使用過P2P終結者或者類似的軟件,你會發覺只要一打開就可以看到局域網內部的所有機器,而有時候我們正好有這樣的需求,那我們應該怎么樣用去獲得局域網的所有機器呢?如果你到百度或者GOOGLE上面進行搜索你會發現,網上大致都是采用輪詢的方法,讓你把所有機器都掃描一遍,如果有反應則表示主機存在,但是這種辦法並不可取,不僅耗資源,而且耗時間,即使你單獨開一個線程去跑,估計半小時都沒有任何結果。網上有人提出更加可笑的辦法,說開多一些線程去檢測。要知道,線程可不是省油的燈,再說,采用輪詢的辦法每遇到一台主機不存在就會拋出一個異常,而且該類異常一般都是超時無響應才拋出的,使用異常處理的方式來處理問題將會嚴重影響應用程序的性能。

這里將介紹如何利用巧妙的方式來獲取局域網內所有機器:

1.先調用系統API判斷網絡是否處於連接狀態

    [DllImport("wininet.dll")]
    private static extern bool InternetGetConnectedState(out int connectionDescription, int reservedValue);
    public static bool IsLocalConnection()
     {
        int connectionDescription = 0;
        return InternetGetConnectedState(out connectionDescription, 0);
    }

2.再調用底層硬件獲取本地網關地址信息

 
            
static string GetGateWayAddress()
{
    ManagementObjectCollection moc = new ManagementClass("Win32_NetworkAdapterConfiguration").GetInstances();
    foreach (ManagementObject mo in moc)
    {
        foreach (PropertyData p in mo.Properties)
        {
            if (p.Name.Equals("DefaultIPGateway") && (p.Value != null))
            {
                string[] strs = p.Value as string[];
                string[] CS$6$0004 = strs;
                int CS$7$0005 = 0;
                while (CS$7$0005 < CS$6$0004.Length)
                {
                    return CS$6$0004[CS$7$0005];
                }
            }
        }
    }
    return "";
}
 
 

3.分別向本地網關內機器發送ICMP數據包

bool Pinging(string addr, int id, uint taskid)
{
    try
    {
        this.m_id = id;
        this.m_taskid = taskid;
        byte[] byReq = this.FillEchoReq();
        IPEndPoint lep = new IPEndPoint(IPAddress.Parse(addr), 0);
        this.socket.SendTo(byReq, lep);
    }
    catch (Exception e)
    {
        Console.WriteLine("Send error:" + e.ToString());
        return false;
    }
    return true;
}
 

4.定義本地機器節點信息類

public class LocalMachine
{
    // Fields
    private string machineIP;
    private string machineMAC;
    private string machineName;

    // Methods
    public LocalMachine();

    // Properties
    public string MachineIP { get; set; }
    public string MachineMAC { get; set; }
    public string MachineName { get; set; }
}
5.根據arp原理,最后通過以下方式讀取arp列表節點信息,其實這里還可以IMCP包響應來獲取主機響應,
不過我個人認為用直接讀取列表的方式更加快速有效。
static ArrayList GetAllLocalMachines()
{
    Process p = new Process();
    p.StartInfo.FileName = "cmd.exe";
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.RedirectStandardInput = true;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.CreateNoWindow = true;
    p.Start();
    p.StandardInput.WriteLine("arp -a");
    p.StandardInput.WriteLine("exit");
    ArrayList list = new ArrayList();
    StreamReader reader = p.StandardOutput;
    string IPHead = Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString().Substring(0, 3);
    for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
    {
        line = line.Trim();
        if (line.StartsWith(IPHead) && (line.IndexOf("dynamic") != -1))
        {
            string IP = line.Substring(0, 15).Trim();
            string Mac = line.Substring(line.IndexOf("-") - 2, 0x11).Trim();
            LocalMachine localMachine = new LocalMachine();
            localMachine.MachineIP = IP;
            localMachine.MachineMAC = Mac;
            localMachine.MachineName = "";
            list.Add(localMachine);
        }
    }
    return list;
}
6.最后,你還可以通過以下方法來獲取網卡的MAC地址信息
[DllImport("NETAPI32.DLL")] public static extern char Netbios(ref MACAddress.NCB ncb);

public string GetMacAddress()
{
    string addr = "";
    try
    {
        NCB Ncb = new NCB();
        Ncb.ncb_command = 0x37;
        int cb = Marshal.SizeOf(typeof(LANA_ENUM));
        Ncb.ncb_buffer = Marshal.AllocHGlobal(cb);
        Ncb.ncb_length = (ushort) cb;
        char uRetCode = Win32API.Netbios(ref Ncb);
        LANA_ENUM lenum = (LANA_ENUM) Marshal.PtrToStructure(Ncb.ncb_buffer, typeof(LANA_ENUM));
        Marshal.FreeHGlobal(Ncb.ncb_buffer);
        if (uRetCode != '


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM