失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 如何高效实现扫描局域网IP 主机名 MAC和端口

如何高效实现扫描局域网IP 主机名 MAC和端口

时间:2019-05-12 12:17:28

相关推荐

如何高效实现扫描局域网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 = 6;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;}

(3)、主要准备工作做好了,接下来,进入主题,如何通过多线程判断IP是否在线。

Thread waitT = new Thread(new ThreadStart(ipwait));waitT.Start();//等待所有线程执行完毕在写入textbox中public void ipwait(){int startIp = Int32.Parse(IPStarttextBox.Text.Split('.')[3]);int endIp = Int32.Parse(IPStoptextBox.Text.Split('.')[3]);ListViewItem lvi;string ip = IPStarttextBox.Text.Split('.')[0] + "." + IPStarttextBox.Text.Split('.')[1] + "." + IPStarttextBox.Text.Split('.')[2] + ".";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++){//---------------------pingipaddr = 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 -1;ResuleTextBox.ScrollToCaret();}ScanResultlistBox.Items[ScanResultlistBox.Items.Count - 1].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('.')[3]);int endIp = Int32.Parse(IPStoptextBox.Text.Split('.')[3]);string ip = IPStarttextBox.Text.Split('.')[0] + "." + IPStarttextBox.Text.Split('.')[1] + "." + IPStarttextBox.Text.Split('.')[2] + ".";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";//---------------------pingPing 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;}//---------------------endThread[] tharr;if (numThread < (portEnd - portStart + 1)){tharr = new Thread[portEnd - portStart + 1];}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 = 0; i < tharr.Length; i++){if (tharr[i] == null)continue;while (tharr[i].IsAlive && iscon)//端口超时设置时间(目前200毫秒),一直等待此ip所有线程执行完毕才扫描下个ip{Thread.Sleep(200);iscon = false;//第一个线程给200ms等待时间,其他线程由于同步执行的,所以没等待时间了,如果线程还没执行完,说明此端口不可达。}}str.Sort();ResuleTextBox.Text += "开放端口: ";for (int k = 0; k < str.Count; k++)ResuleTextBox.Text += str[k] + " ";ResuleTextBox.Text += "\n";}ScanResultlistBox.Items[ScanResultlistBox.Items.Count - 1].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 = 0; 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 80:return "HTTP协议代理服务";case 135:return "DCE endpoint resolutionnetbios-ns";case 445:return "安全服务";case 1025:return "NetSpy.698(YAI)";case 8080:return "HTTP协议代理服务";case 8081:return "HTTP协议代理服务";case 3128:return "HTTP协议代理服务";case 9080:return "HTTP协议代理服务";case 1080:return "SOCKS代理协议服务";case 21:return "FTP(文件传输)协议代理服务";case 23:return "Telnet(远程登录)协议代理服务";case 443:return "HTTPS协议代理服务";case 69:return "TFTP协议代理服务";case 22:return "SSH、SCP、端口重定向协议代理服务";case 25:return "SMTP协议代理服务";case 110: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());}}

好了,大家最后,可能都会说,我不想设计,也不想开发,我想要现成的怎么办?当然了,最后附上程序,大家可以实际进行测试使用。

工具链接:/detail/dwx1005526886/9808540

如果觉得《如何高效实现扫描局域网IP 主机名 MAC和端口》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。