用C#获取局域网内所有机器

来源:互联网 发布:孙巍 悦游网络 编辑:程序博客网 时间:2024/06/06 15:46
如果你使用过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 getset; }
    
public string MachineMAC getset; }
    
public string MachineName getset; }
}

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(03);
    
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(015).Trim();
            
string Mac = line.Substring(line.IndexOf("-"- 20x11).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 != '
原创粉丝点击