首先非常感谢Melou的http://www.cnblogs.com/luoht/archive/2009/12/18/1627431.html的随笔,对于初学C#的我,参考你的随笔对我的学习真是有莫大帮助。
C#遍历局域网的几种方法:
1、微软社区上介绍了使用Active Directory 来遍历局域网
首先我们来了解DirectoryEntry类是一个什么类。
命名空间: System.DirectoryServices
程序集: System.DirectoryServices(在 System.DirectoryServices.dll 中)
DirectoryEntry类可封装Active Directory 域服务层次结构中的节点或对象。
其中有构造函数
DirectoryEntry(String),初始化 DirectoryEntry 类的新实例,该类将此实例绑定到位于指定路径的 Active Directory 域服务中的节点。
链接:https://msdn.microsoft.com/zh-cn/library/system.directoryservices.directoryentry.aspx
我们必须了解其中的Active Directory
使用 Active Directory(R) 域服务 (AD DS) 服务器角色,可以创建用于用户和资源管理的可伸缩、安全及可管理的基础机构,并可以提供对启用目录的应用程序(如 Microsoft(R) Exchange Server)的支持。
AD DS 提供了一个分布式数据库,该数据库可以存储和管理有关网络资源的信息,以及启用了目录的应用程序中特定于应用程序的数据。运行 AD DS 的服务器称为域控制器。管理员可以使用 AD DS 将网络元素(如用户、计算机和其他设备)整理到层次内嵌结构。内嵌层次结构包括 Active Directory 林、林中的域以及每个域中的组织单位 (OU)。
链接:https://technet.microsoft.com/zh-cn/library/hh831484.aspx
接下来看怎么利用DirectoryEntry
利用DirectoryEntry组件来查看网络
//C# 操作WINNT本地用户和组
DirectoryEntry DEMain = new DirectoryEntry("WinNT:");
foreach(DirectoryEntry DEGroup in DEMain.Children)
{
//如果和选择的用户组相同
if(DEGroup.Name.ToLower() == comb_workgroup.Text.ToLower())
{
//读出用户组下的每一个主机名
foreach(DirectoryEntry DEComputer in DEGroup.Children)
{
//滤掉无效结果 Computer: Schema
if(DEComputer.Name.ToLower() != "schema")
{
listb_computer.Items.Add(DEComputer.Name);
}
}
}
}
效果评价:速度慢,效率低,还有一个无效结果 Computer: Schema 使用的过程中注意虑掉。
2、利用Dns.GetHostByAddress和IPHostEntry遍历局域网
Dns.GetHostByAddress类:返回指定主机的 Internet 协议 (IP) 地址。
命名空间: System.Net
程序集: System(在 System.dll 中)
public static IPAddress[] GetHostAddresses(
string hostNameOrAddress
)
IPHostEntry类:为 Internet 主机地址信息提供容器类。
命名空间: System.Net
程序集: System(在 System.dll 中)
private void EnumComputers2()
{
//从192.168.0.1 到 192.168.0.255开始依次尝试
for (int i = 1; i <= 255; i++)
{
string scanIP = "192.168.0." + i.ToString();
IPAddress myScanIP = IPAddress.Parse(scanIP);
IPHostEntry myScanHost = null;
try
{
//获取myScanIP的IP地址
myScanHost = Dns.GetHostByAddress(myScanIP);
}
catch
{
continue;
}
if (myScanHost != null)
{
//返回IP和主机名
Console.WriteLine(scanIP + "|" + myScanHost.HostName);
}
}
}
System.Net.NetworkInformation.Ping类:允许应用程序确定是否可通过网络访问远程计算机。
命名空间:System.Net.NetworkInformation
程序集:System(在 system.dll 中)
delegate void WT(int n);
Thread t;
private string GetMacAddress(string hostip)//获取远程IP(不能跨网段)的MAC地址
{
string Mac = "";
try
{
Int32 ldest = inet_addr(hostip); //将IP地址从 点数格式转换成无符号长整型
Int64 macinfo = new Int64();
Int32 len = 6;
//SendARP函数发送一个地址解析协议(ARP)请求获得指定的目的地IPv4地址相对应的物理地址
SendARP(ldest, 0, ref macinfo, ref len);
string TmpMac = Convert.ToString(macinfo, 16).PadLeft(12, '0');//转换成16进制 注意有些没有十二位
Mac = TmpMac.Substring(0, 2).ToUpper();//
for (int i = 2; i < TmpMac.Length; i = i + 2)
{
Mac = TmpMac.Substring(i, 2).ToUpper() + "-" + Mac;
}
}
catch (Exception Mye)
{
Mac = "获取远程主机的MAC错误:" + Mye.Message;
}
return Mac;
}
private void EnumComputers(int n)
{
//lock (this)
//Invoke(new MethodInvoker(delegate()
//{
//注册委托
if (this.txtAddrs.InvokeRequired)
{
WT d = new WT(EnumComputers);
this.Invoke(d, new object[] { n });
}
else
{
try
{
for (int i = 0; i <= 255; i++)
{
Ping myPing;
myPing = new Ping();
//当发送 Internet 控制消息协议 (ICMP) 回送消息并接收相应 ICMP 回送答复消息的异步操作完成或被取消时发生。
myPing.PingCompleted += new PingCompletedEventHandler(myPing_PingCompleted);
string pingIP = "192.168." + n.ToString() + "." + i.ToString();
//尝试以异步方式向指定的计算机发送Internet控制消息协议(ICMP)回送消息,并从该计算机接收相应的ICMP回送答复消息。
myPing.SendAsync(pingIP, 1000, null);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//}));
}
private void myPing_PingCompleted(object sender, PingCompletedEventArgs e)
{
StringBuilder sb = new StringBuilder();
if (e.Reply.Status == IPStatus.Success)
{
sb.Append("IP:" + e.Reply.Address.ToString() + "\r\n");
//获取MAC地址
string mac = GetMacAddress(e.Reply.Address.ToString());
sb.Append("MAC:" + mac + "\r\n\r\n");
num++;
}
this.txtAddrs.Text += sb.ToString();
//this.lbIPs.Text = "在线IP数:" + num.ToString();
this.lbIPs.Text = num.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
this.txtAddrs.Text = "";
num = 0;
t = new Thread(() => EnumComputers((int)(this.txtIP2.Value)));
t.IsBackground = true;
t.Start();
//EnumComputers((int)(this.txtIP2.Value));
}
需要注意的是取计算机名称如果用Dns.GetHostByAddress取计算机名称,结果虽然正确,但VS2005会提示该方法已过时,但仍能使用。
如果用它推荐的替代方法Dns.GetHostEntry,则有个别计算机的名称会因超时而获得不到。
4、端口扫描:利用TcpClient判断端口是否打开
命名空间: System.Net.Sockets
程序集: System.Net.Sockets(在 System.Net.Sockets.dll 中)
System(在 System.dll 中)
delegate void WT2();
Thread t;
private void scanport()
{
if (this.txtAddrs.InvokeRequired)
{
WT2 d = new WT2(scanport);
this.Invoke(d, null);
}
else
{
try
{
TcpClient client = new TcpClient();
IPAddress address = IPAddress.Parse(txtIP.Text);
for (int i = int.Parse(this.txtBegin.Text); i <= int.Parse(this.txtEnd.Text); i++)
{
try
{
client.Connect(address, i);
txtAddrs.AppendText("端口 " + i + " 是打开的\n");
Console.WriteLine("端口{0}是打开的",i);
client = new System.Net.Sockets.TcpClient();
}
catch
{
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
附上两个获取局域网IP及其主机端口号的代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.Net.Sockets;
namespace 获取局域网IP和MAC地址
{
public partial class Form1 : Form
{
delegate void WT(int n);
delegate void WT2();
Thread t;
public Form1()
{
InitializeComponent();
}
[DllImport("ws2_32.dll")]
private static extern int inet_addr(string cp);
[DllImport("IPHLPAPI.dll")]
private static extern int SendARP(Int32 DestIP, Int32 ScrIP, ref Int64 pMacAddr, ref Int32 PhyAddrLen);
//ref和out在C#中既可以通过值引用传递参数。通过引用参数传递参数允许函数成员更改参数的值
//并保持该更改。若要通过引用传递参数,可以使用ref或者out关键字。ref和out这两个关键字都
//能够提供相似的功效,其作用很像C中的指针变量
//使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。
//使用ref和out时,在方法的参数和执行方法时,都要加Ref或Out关键字。以满足匹配。
//out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。
private string GetMacAddress(string hostip)//获取远程IP(不能跨网段)的MAC地址
{
string Mac = "";
try
{
Int32 ldest = inet_addr(hostip); //将IP地址从 点数格式转换成无符号长整型
Int64 macinfo = new Int64();
Int32 len = 6;
//SendARP函数发送一个地址解析协议(ARP)请求获得指定的目的地IPv4地址相对应的物理地址
SendARP(ldest, 0, ref macinfo, ref len);
string TmpMac = Convert.ToString(macinfo, 16).PadLeft(12, '0');//转换成16进制 注意有些没有十二位
Mac = TmpMac.Substring(0, 2).ToUpper();//
for (int i = 2; i < TmpMac.Length; i = i + 2)
{
Mac = TmpMac.Substring(i, 2).ToUpper() + "-" + Mac;
}
}
catch (Exception Mye)
{
Mac = "获取远程主机的MAC错误:" + Mye.Message;
}
return Mac;
}
private void button1_Click(object sender, EventArgs e)
{
this.txtMAC.Text = GetMacAddress(this.txtIP.Text.Trim());
}
private List<string> ShowIP()
{
List<string> ipv4list = new List<string>();
//ipv4地址也可能不止一个
foreach (string ip in GetLocalIpv4())
{
//this.richTextBoxIPv4.AppendText(ip.ToString());
//Console.WriteLine(ip.ToString());
ipv4list.Add(ip.ToString());
}
return ipv4list;
}
private string[] GetLocalIpv4()
{
//事先不知道ip的个数,数组长度未知,因此用StringCollection储存
IPAddress[] localIPs;
localIPs = Dns.GetHostAddresses(Dns.GetHostName());
StringCollection IpCollection = new StringCollection();
foreach (IPAddress ip in localIPs)
{
//根据AddressFamily判断是否为ipv4,如果是InterNetWorkV6则为ipv6
if (ip.AddressFamily == AddressFamily.InterNetwork)
IpCollection.Add(ip.ToString());
}
string[] IpArray = new string[IpCollection.Count];
IpCollection.CopyTo(IpArray, 0);
return IpArray;
}
private void Form1_Load(object sender, EventArgs e)
{
List<string> list = ShowIP();
foreach(string str in list)
{
if(str.Contains("192.168."))
{
txtIP.Text = str;
}
}
}
private void button3_Click(object sender, EventArgs e)
{
if (Dns.GetHostEntry(Dns.GetHostName()).AddressList.Length > 0)
{
txtAddrs.Text = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();//获取本机IPv6地址
}
}
private void EnumComputers2()
{
//从192.168.0.1 到 192.168.0.255开始依次尝试
for (int i = 1; i <= 255; i++)
{
string scanIP = "192.168.0." + i.ToString();
IPAddress myScanIP = IPAddress.Parse(scanIP);
IPHostEntry myScanHost = null;
try
{
//获取myScanIP的IP地址
myScanHost = Dns.GetHostByAddress(myScanIP);
}
catch
{
continue;
}
if (myScanHost != null)
{
//返回IP和主机名
Console.WriteLine(scanIP + "|" + myScanHost.HostName);
}
}
}
private void EnumComputers(int n)
{
//lock (this)
//Invoke(new MethodInvoker(delegate()
//{
//注册委托
if (this.txtAddrs.InvokeRequired)
{
WT d = new WT(EnumComputers);
this.Invoke(d, new object[] { n });
}
else
{
try
{
for (int i = 0; i <= 255; i++)
{
Ping myPing;
myPing = new Ping();
//当发送 Internet 控制消息协议 (ICMP) 回送消息并接收相应 ICMP 回送答复消息的异步操作完成或被取消时发生。
myPing.PingCompleted += new PingCompletedEventHandler(myPing_PingCompleted);
string pingIP = "192.168." + n.ToString() + "." + i.ToString();
//尝试以异步方式向指定的计算机发送Internet控制消息协议(ICMP)回送消息,并从该计算机接收相应的ICMP回送答复消息。
myPing.SendAsync(pingIP, 1000, null);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//}));
}
private static int num = 0;
private void myPing_PingCompleted(object sender, PingCompletedEventArgs e)
{
StringBuilder sb = new StringBuilder();
if (e.Reply.Status == IPStatus.Success)
{
sb.Append("IP:" + e.Reply.Address.ToString() + "\r\n");
//获取MAC地址
string mac = GetMacAddress(e.Reply.Address.ToString());
sb.Append("MAC:" + mac + "\r\n\r\n");
num++;
}
this.txtAddrs.Text += sb.ToString();
//this.lbIPs.Text = "在线IP数:" + num.ToString();
this.lbIPs.Text = num.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
this.txtAddrs.Text = "";
num = 0;
t = new Thread(() => EnumComputers((int)(this.txtIP2.Value)));
t.IsBackground = true;
t.Start();
//EnumComputers((int)(this.txtIP2.Value));
}
private void button4_Click(object sender, EventArgs e)
{
t = new Thread(() => scanport());
t.IsBackground = true;
t.Start();
}
private void scanport()
{
if (this.txtAddrs.InvokeRequired)
{
WT2 d = new WT2(scanport);
this.Invoke(d, null);
}
else
{
try
{
TcpClient client = new TcpClient();
IPAddress address = IPAddress.Parse(txtIP.Text);
for (int i = int.Parse(this.txtBegin.Text); i <= int.Parse(this.txtEnd.Text); i++)
{
try
{
client.Connect(address, i);
txtAddrs.AppendText("端口 " + i + " 是打开的\n");
Console.WriteLine("端口{0}是打开的",i);
client = new System.Net.Sockets.TcpClient();
}
catch
{
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private void txtIP2_ValueChanged(object sender, EventArgs e)
{
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.DirectoryServices;
using System.Net.Sockets;
using System.Threading;
namespace 端口扫描
{
public partial class Form1 : Form
{
#region
//C# 操作WINNT本地用户和组
DirectoryEntry DEMain = new DirectoryEntry("WinNT:");
TcpClient TClient = null;
private Thread myThread;
string strName = "";
int intflag = 0;
int intport = 0;
int intstart = 0;
int intend = 0;
#endregion
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//遍历局域网中的工作组,并显示在下拉列表控件中
foreach(DirectoryEntry DEGroup in DEMain.Children)
{
comb_workgroup.Items.Add(DEGroup.Name);
}
}
private void comb_workgroup_SelectedIndexChanged(object sender, EventArgs e)
{
listb_computer.Items.Clear();
//遍历本地用户组
foreach(DirectoryEntry DEGroup in DEMain.Children)
{
//如果和选择的用户组相同
if(DEGroup.Name.ToLower() == comb_workgroup.Text.ToLower())
{
//读出用户组下的每一个主机名
foreach(DirectoryEntry DEComputer in DEGroup.Children)
{
//滤掉无效结果 Computer: Schema
if(DEComputer.Name.ToLower() != "schema")
{
listb_computer.Items.Add(DEComputer.Name);
}
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
richtxt_port.Items.Clear();
try
{
if(button1.Text == "扫描")
{
intport = 0;
progressBar1.Minimum = Convert.ToInt32(txt_beginport.Text);
progressBar1.Maximum = Convert.ToInt32(txt_endport.Text);
progressBar1.Value = progressBar1.Minimum;
timer1.Start();
button1.Text = "停止";
intstart = Convert.ToInt32(txt_beginport.Text);
intend = Convert.ToInt32(txt_endport.Text);
myThread = new Thread(new ThreadStart(this.StartScan));
myThread.Start();
}
else
{
button1.Text = "扫描";
timer1.Stop();
progressBar1.Value =Convert.ToInt32(txt_endport.Text);
if(myThread != null)
{
if(myThread.ThreadState == ThreadState.Running)
{
myThread.Abort();
}
}
}
}
catch { }
}
private void StartScan()
{
while(true)
{
for(int i = intstart;i<=intend;i++)
{
intflag = i;
try
{
TClient = new TcpClient(strName, i);
intport = i;
}
catch { }
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if(intport != 0)
{
if (richtxt_port.Items.Count > 0)
{
for (int i = 0; i < richtxt_port.Items.Count; i++)
{
if (richtxt_port.Items[i].Text != intport.ToString())
{
richtxt_port.Items.Add(intport.ToString());
}
}
}
else
richtxt_port.Items.Add(intport.ToString());
}
if (progressBar1.Value < progressBar1.Maximum)
progressBar1.Value += 1;
if(intflag == Convert.ToInt32(txt_endport.Text))
{
timer1.Stop();
button1.Text = "扫描";
MessageBox.Show("端口扫描结束!");
}
}
}
}