如何高效实现扫描局域网IP、主机名、MAC和端口
近几年工作经常使用RFID识读器,智能家居网关,温湿度传感器、串口服务器、视频编码器等,一般是有串口和网口,由于现场原因一般较少使用串口,大多使用网口。连接方法是IP地址和端口,有的设备带搜索软件,有的就不带。经常测试环境和现场来回用,难免记混。同时使用网上的一些端口扫描工具,发现有一个问题,就是在进行扫描的时候,不怎么好用,比如,扫描器一般都是带端口扫描的,但是,我仅仅只用扫描设备在不在线,不用扫描端口,但是有一些设备是只要扫描端口,这个怎么更方便更好用呢?
同时在扫描成功之后,需要通过TCP连接到设备,发数据,看数据能不能正常相应,或者设备状态对不对,这是不是又要单独开另外一个软件?使用起来,比较繁琐,因此就根据自己的需要制作了一个小工具,用来扫描IP和端口。
扫描速度一定要快,成功和不成功区分要明显,好了,先上图:

一、主要IP扫描方法:
(1)、IP地址匹配,看IP设置是否正确
//匹配正确的IP地址
Regex rgx = new Regex(@"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"); if (rgx.IsMatch(IPStarttextBox.Text) && rgx.IsMatch(IPStoptextBox.Text))//匹配正确IP
{
if (scan_type == 1)
{
int startIp = Int32.Parse(IPStarttextBox.Text.Split('.')[3]);
int endIp = Int32.Parse(IPStoptextBox.Text.Split('.')[3]);
progressBar.Minimum = startIp;
progressBar.Maximum = endIp;
}
else
{
if (PortStarttextBox.Text == "")
{
MessageBox.Show("请输入端口号!");
}
else
{
portStart = Int32.Parse(PortStarttextBox.Text);
portEnd = Int32.Parse(PortEndtextBox.Text);
progressBar.Minimum = portStart;
progressBar.Maximum = portEnd;
} if (portEnd < portStart)
{
MessageBox.Show("请填写正确端口范围");
return;
}
} }
else
{
MessageBox.Show("请填写正确IP");
return;
}
(2)、获取主机名
public static string GetHostEntry(object ip)
{
string hostname = "-";
try
{
IPHostEntry host = Dns.GetHostEntry(ip.ToString());
hostname = host.HostName;
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
return hostname;
}
(3)、获取MAC地址
[DllImport("ws2_32.dll")]
private static extern int inet_addr(string cp);
[DllImport("IPHLPAPI.dll")]
private static extern int SendARP(Int32 DestIP, Int32 SrcIP, ref Int64 pMacAddr, ref Int32 PhyAddrLen);
private string GetMacAddress(string hostip)//获取远程IP(不能跨网段)的MAC地址
{
string Mac = "";
try
{
Int32 ldest = inet_addr(hostip); //将IP地址从 点数格式转换成无符号长整型
Int64 macinfo = new Int64();
Int32 len = ;
SendARP(ldest, , ref macinfo, ref len);
string TmpMac = Convert.ToString(macinfo, ).PadLeft(, '');//转换成16进制 注意有些没有十二位
Mac = TmpMac.Substring(, ).ToUpper();//
for (int i = ; i < TmpMac.Length; i = i + )
{
Mac = TmpMac.Substring(i, ).ToUpper() + "-" + Mac;
}
}
catch (Exception Mye)
{
Mac = "获取远程主机的MAC错误:" + Mye.Message;
}
return Mac;
}
(3)、主要准备工作做好了,接下来,进入主题,如何通过多线程判断IP是否在线。
Thread waitT = new Thread(new ThreadStart(ipwait));
waitT.Start();//等待所有线程执行完毕在写入textbox中 public void ipwait()
{
int startIp = Int32.Parse(IPStarttextBox.Text.Split('.')[]);
int endIp = Int32.Parse(IPStoptextBox.Text.Split('.')[]);
ListViewItem lvi; string ip = IPStarttextBox.Text.Split('.')[] + "." + IPStarttextBox.Text.Split('.')[] + "." + IPStarttextBox.Text.Split('.')[] + ".";
String ipaddr = "";
int timeout = int.Parse(TimeOuttextBox.Text); string mac = ""; progressBar.Minimum = startIp;
progressBar.Maximum = endIp;
try
{ for (int q = startIp; q <= endIp && isrun == true; q++)
{ //---------------------ping
ipaddr = ip + q;
lvi = new ListViewItem();
Ping ping = new Ping();
PingReply reply = ping.Send(IPAddress.Parse(ipaddr), overTime); if (reply.Status == IPStatus.Success)
{ ResuleTextBox.Text += ipaddr + " Ping时间 " + reply.RoundtripTime + " 毫秒\n";
mac= GetMacAddress(ipaddr);
// IPHostEntry host = Dns.GetHostEntry(ipaddr);
// IPHostEntry host = Dns.GetHostByAddress(ipaddr);
// ResuleTextBox.Text += "主机名为 " + host.HostName + "\n";
// ScanResultlistBox.Items.Add(ipaddr + " " + mac + " 在线 ");
lvi.BackColor = Color.LightSeaGreen;
lvi.Text = ipaddr;
Task<string> t1 = new Task<string>(GetHostEntry,ipaddr);
t1.Start();
t1.Wait(timeout); //设置获取主机名超时时间
if(t1.IsCompleted)
{
lvi.SubItems.Add(t1.Result);
}
else
{
lvi.SubItems.Add("-");
}
lvi.SubItems.Add(mac);
lvi.SubItems.Add("在线"); }
else
{
lvi.BackColor = Color.Pink;
lvi.Text = ipaddr;
lvi.SubItems.Add("-");
lvi.SubItems.Add("-");
lvi.SubItems.Add("不在线");
} progressBar.Value = q;
progressBar.Update();
ListViewUpdate(lvi);
ResuleTextBox.SelectionStart = ResuleTextBox.Text.Length -;
ResuleTextBox.ScrollToCaret();
}
ScanResultlistBox.Items[ScanResultlistBox.Items.Count - ].EnsureVisible(); }
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
isrun = false;
progressBar.Value = progressBar.Minimum;
startScanbutton.Enabled = true;
stopScanbutton.Enabled = false;
ResuleTextBox.Text += ex.ToString();
}
startScanbutton.Enabled = true;
stopScanbutton.Enabled = false;
isrun = false;
progressBar.Value = progressBar.Maximum; }
说明一下:在我获取主机名的过程中,发现如果不对获取主机名设置一个超时时间,那么将会出现一个问题,程序将会卡在获取主机名的这个阶段,无法向下继续执行,因为,为了高效的执行,给获取主机名设置一个超时时间,将会大大提高程序的执行效率。
二、主要端口状态获取方法
Thread waitT = new Thread(new ThreadStart(portwait));
waitT.Start();//等待所有线程执行完毕在写入textbox中
public void portwait()
{
int startIp = Int32.Parse(IPStarttextBox.Text.Split('.')[]);
int endIp = Int32.Parse(IPStoptextBox.Text.Split('.')[]); string ip = IPStarttextBox.Text.Split('.')[] + "." + IPStarttextBox.Text.Split('.')[] + "." + IPStarttextBox.Text.Split('.')[] + ".";
String mac = "" , ipaddr ="";
ListViewItem lvi;
String host;
int timeout = int.Parse(TimeOuttextBox.Text);
for (int q = startIp; q <= endIp && isrun == true; q++)
{
ResuleTextBox.Text += (ip + q) + " IP地址扫描中---\n";
//---------------------ping
Ping ping = new Ping(); PingReply reply = ping.Send(IPAddress.Parse(ip + q), overTime);
ipaddr = ip + q;
if (reply.Status == IPStatus.Success)
{
ResuleTextBox.Text +=ipaddr + " Ping时间" + reply.RoundtripTime + "毫秒\n";
mac = GetMacAddress(ipaddr);
Task<string> t1 = new Task<string>(GetHostEntry, ipaddr);
t1.Start();
t1.Wait(timeout);
if (t1.IsCompleted)
{
host = t1.Result.ToString();
}
else
{
host = "-";
}
ResuleTextBox.Text += "MAC地址为 " + mac + "\n";
}
else
{
// ScanResultlistBox.Items.Add(ipaddr + " " + "-" + " " + "-" + " " + " - 不可达\n");
lvi = new ListViewItem();
lvi.BackColor = Color.Pink;
lvi.Text = ipaddr;
lvi.SubItems.Add("-");
lvi.SubItems.Add("-");
lvi.SubItems.Add("不可达");
ResuleTextBox.Text += ipaddr + "不可达\n";
ListViewUpdate(lvi);
continue;
} //---------------------end
Thread[] tharr;
if (numThread < (portEnd - portStart + ))
{
tharr = new Thread[portEnd - portStart + ];
}
else
{
tharr = new Thread[numThread];
}
str = new List<string>();
for (int i = portStart; (i <= portEnd) && (isrun ==true); i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Scan));
thread.Start(new IPEndPoint(IPAddress.Parse(ip + q), i));//每扫描一个端口创建一个线程 ResuleTextBox.Text += i + " 端口扫描中---\n"; tharr[i - portStart] = thread;
progressBar.Value = i; string s = State(i); lvi = new ListViewItem(); if (s == "Open")
{
lvi.BackColor = Color.LightSeaGreen;
}
else
{
lvi.BackColor = Color.Silver;
} lvi.Text = ipaddr + ":" + i.ToString();
lvi.SubItems.Add(host);
lvi.SubItems.Add(mac); if (checkBox1.Checked)
{
if (s == "Open")
{ // ScanResultlistBox.Items.Add(ip + q + " " + mac +" "+ i + " " + s + " " + " " + Service(i)); lvi.SubItems.Add(i.ToString());
lvi.SubItems.Add(s);
lvi.SubItems.Add(Service(i));
}
else
{
lvi = null;
}
}
else
{
if (s == "Open")
{ // ScanResultlistBox.Items.Add(ip + q + " " + mac + " " + i + " " + s + " " + " " + Service(i)); lvi.SubItems.Add(i.ToString());
lvi.SubItems.Add(s);
lvi.SubItems.Add(Service(i));
}
else
{
// ScanResultlistBox.Items.Add(ip + q + " " + mac + " " + i + " " + s + " " + " "); lvi.SubItems.Add(i.ToString());
lvi.SubItems.Add(s);
lvi.SubItems.Add("");
}
}
if (lvi != null)
{
ListViewUpdate(lvi);
}
} bool iscon = true;//第一个线程等待时间
for (int i = ; i < tharr.Length; i++)
{
if (tharr[i] == null)
continue;
while (tharr[i].IsAlive && iscon)//端口超时设置时间(目前200毫秒),一直等待此ip所有线程执行完毕才扫描下个ip
{
Thread.Sleep();
iscon = false;//第一个线程给200ms等待时间,其他线程由于同步执行的,所以没等待时间了,如果线程还没执行完,说明此端口不可达。
}
}
str.Sort();
ResuleTextBox.Text += "开放端口: ";
for (int k = ; k < str.Count; k++)
ResuleTextBox.Text += str[k] + " ";
ResuleTextBox.Text += "\n";
}
ScanResultlistBox.Items[ScanResultlistBox.Items.Count - ].EnsureVisible();
if (isrun == true)
{
MessageBox.Show("扫描完成");
progressBar.Value = progressBar.Minimum;
startScanbutton.Enabled = true;
stopScanbutton.Enabled = false;
isrun = false;
}
else
{
MessageBox.Show("扫描终止");
startScanbutton.Enabled = true;
stopScanbutton.Enabled = false;
progressBar.Value = progressBar.Minimum;
isrun = false;
} }
public string State(int i)
{
str.Sort();
for (int k = ; k < str.Count; k++)
{
string s = str[k];
if (Convert.ToString(i) == s)
return "Open";
}
return "Closed";
}
public string Service(int i)
{
switch (i)
{ case :
return "HTTP协议代理服务";
case :
return "DCE endpoint resolutionnetbios-ns";
case :
return "安全服务";
case :
return "NetSpy.698(YAI)"; case :
return "HTTP协议代理服务"; case :
return "HTTP协议代理服务"; case :
return "HTTP协议代理服务"; case :
return "HTTP协议代理服务"; case :
return "SOCKS代理协议服务"; case :
return "FTP(文件传输)协议代理服务"; case :
return "Telnet(远程登录)协议代理服务"; case :
return "HTTPS协议代理服务"; case :
return "TFTP协议代理服务"; case :
return "SSH、SCP、端口重定向协议代理服务"; case :
return "SMTP协议代理服务"; case :
return "POP3协议代理服务";
default:
return "Unknow Servies"; }
} public void Scan(object Point)
{
IPEndPoint IPPoint = (IPEndPoint)Point;
try
{
TcpClient tcp = new TcpClient();
tcp.Connect(IPPoint);
if (tcp.Connected)
str.Add(Convert.ToString(IPPoint.Port));
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
好了,大家最后,可能都会说,我不想设计,也不想开发,我想要现成的怎么办?当然了,最后附上程序,大家可以实际进行测试使用。
工具链接:http://download.csdn.net/detail/dwx1005526886/9808540
如何高效实现扫描局域网IP、主机名、MAC和端口的更多相关文章
- python获取主机IP,主机名
获取主机内网,外网IP,主机名 代码如下: #!/usr/bin/env python #-*- coding:utf-8 -*- # author:Zeng Xianhe import socket ...
- 调用python-nmap实现扫描局域网存活主机
使用环境:Raspberry 3b+ +netifaces+python-nmap+nmap 调用netifaces自动获取ip地址: def get_gateways(): return netif ...
- linux系统的初化始配置 IP 主机名 防火墙 selinux
本次内容包括Linux:ip.主机名.关闭firewalld与selinux 开机临时生效和永久生效 ------------------------------------------------- ...
- java 代码,练习ip,主机名的获取方法。InetAddress类
package clientFrame; import java.io.IOException; import java.net.*; public class tai { public static ...
- 用arp-scan扫描局域网IP地址
1,在安装之前需要安装yum install -y libpcap libpcap-devel如果没有安装yum工具需要用rpm安装如下软件包[root@oradba arp-scan-1.8]# y ...
- c# 扫描局域网IP列表的几种方法
很多软件都有获知局域网在线计算机IP的功能,但是在.net怎么实现呢,有好多方法, 下面我给大家介绍几种,供大家参考. 1.微软社区上介绍了使用Active Directory 来遍历局域网 利用Di ...
- 扫描局域网ip的shell
# vim /mysh/ipscan.sh #!/bin/bash # scan the local alive ipaddress # -- if [ -f $filename ];then ech ...
- 扫描局域网ip存活
#!/bin/bash # #******************************************************************** #encoding -*-utf ...
- Linux学习(一):linux更改ip地址命令_更改DNS_更改默认网关_更改子网掩码_主机名
如何使用命令来更改linux的IP .DNS .子网掩码,在虚拟机(vitrualBox)上添加一个Linux的虚拟机; 安装方法:http://pan.baidu.com/s/1sjJPhP7 安装 ...
随机推荐
- 【CNMP系列】CentOS7.0下安装MySql5.6服务
接上一回的话,CentOS7.0下安装好了Nginx服务,对于我们的CNMP,我们可以开始我们的M啦,就是传统意义上的MySql服务 MySql简介 MySQL是一个关系型数据库管理系统,由瑞典MyS ...
- p1144一元三次方程求解
题目描述: 有形如:f(x)=ax^3+bx^2+cx+d=0这样的一元三次方程,给出该方程中各项的系数a,b,c,d,它们均为实数,并约定该方程一定存在着3个不同的实数解,解的范围在-100至100 ...
- SpringMVC4+MyBatis3+SQLServer 2014 整合(包括增删改查分页)
前言 说起整合自然离开ssm,我本身并不太喜欢ORM,尤其是MyBatis,把SQL语句写在xml里,尤其是大SQL,可读性不高,出错也不容易排查. 开发环境 idea2016.SpringMVC4. ...
- 安全体系(二)——RSA算法详解
本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 ...
- shell [ff: 未找到命令
在学习shell脚本时遇到一个问题: [ff: 未找到命令 相信很多初学者都会遇到,再次说明一下,希望对大家有所帮助: shell脚本代码如下: #!/bin/bash echo -n " ...
- 【RecyclerView与Glide】实现一个Android电子书阅读APP
http://www.cnblogs.com/xfangs/ 欢迎在本文下方评论,小方很需要鼓励支持!!! 本系列教程仅供学习交流 小说阅读器最终实现效果见 第一篇博文 前言 在上一篇文章中,我们实现 ...
- 3377: [Usaco2004 Open]The Cow Lineup 奶牛序列
3377: [Usaco2004 Open]The Cow Lineup 奶牛序列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 16 Solved ...
- IOS本地日志记录方案
我们在项目中日志记录这块也算是比较重要的,有时候用户程序出什么问题,光靠服务器的日志还不能准确的找到问题. 现在一般记录日志有几种方式: 1.使用第三方工具来记录日志,如腾讯的Bugly,它是只把程序 ...
- ES4:ElasticSearch 使用C#添加和更新文档
这是ElasticSearch 2.4 版本系列的第四篇: 第一篇:ES1:Windows下安装ElasticSearch 第二篇:ES2:ElasticSearch 集群配置 第三篇:ES3:Ela ...
- (转载)一个生动的NIO描述
原文地址:http://blog.csdn.net/zhouhl_cn/article/details/6568119 传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大 ...