近几年工作经常使用 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 stringGetHostEntry(object ip)
- {
- stringhostname ="-";
- 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 intinet_addr(string cp);
- [DllImport("IPHLPAPI.dll")]
- private static extern intSendARP(Int32 DestIP, Int32 SrcIP,refInt64 pMacAddr,ref Int32 PhyAddrLen);
- private stringGetMacAddress(stringhostip)//获取远程IP(不能跨网段)的MAC地址
- {
- stringMac ="";
- try
- {
- Int32 ldest = inet_addr(hostip);//将IP地址从 点数格式转换成无符号长整型Int64 macinfo =new Int64();
- Int32 len =6;
- SendARP(ldest, 0,refmacinfo,ref len);
- stringTmpMac = Convert.ToString(macinfo,16).PadLeft(12,'0');//转换成16进制注意有些没有十二位Mac = TmpMac.Substring(0,2).ToUpper();//
- for(inti =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 =newThread(new ThreadStart(ipwait));
- waitT.Start();//等待所有线程执行完毕在写入textbox中
- public void ipwait()
- {
- intstartIp = Int32.Parse(IPStarttextBox.Text.Split('.')[3]);
- intendIp = Int32.Parse(IPStoptextBox.Text.Split('.')[3]);
- ListViewItem lvi;
- stringip = IPStarttextBox.Text.Split('.')[0] +"."+ IPStarttextBox.Text.Split('.')[1] +"."+ IPStarttextBox.Text.Split('.')[2] +".";
- String ipaddr ="";
- inttimeout =int.Parse(TimeOuttextBox.Text);
- stringmac ="";
- progressBar.Minimum = startIp;
- progressBar.Maximum = endIp;
- try
- {
- for(intq = 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 =newTask<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 =newThread(new ThreadStart(portwait));
- waitT.Start();//等待所有线程执行完毕在写入textbox中
- public void portwait()
- {
- intstartIp = Int32.Parse(IPStarttextBox.Text.Split('.')[3]);
- intendIp = Int32.Parse(IPStoptextBox.Text.Split('.')[3]);
- stringip = IPStarttextBox.Text.Split('.')[0] +"."+ IPStarttextBox.Text.Split('.')[1] +"."+ IPStarttextBox.Text.Split('.')[2] +".";
- String mac ="", ipaddr ="";
- ListViewItem lvi;
- String host;
- inttimeout =int.Parse(TimeOuttextBox.Text);
- for(intq = 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 =newTask<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 +1))
- {
- tharr =newThread[portEnd - portStart +1];
- }
- else
- {
- tharr =new Thread[numThread];
- }
- str =newList<string>();
- for(inti = portStart; (i <= portEnd) && (isrun ==true); i++)
- {
- Thread thread =newThread(new ParameterizedThreadStart(Scan));
- thread.Start(newIPEndPoint(IPAddress.Parse(ip + q), i));//每扫描一个端口创建一个线程
- ResuleTextBox.Text += i +" 端口扫描中---\n";
- tharr[i - portStart] = thread;
- progressBar.Value = i;
- strings = 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);
- }
- }
- booliscon =true;//第一个线程等待时间
- for(inti =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(intk =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 stringState(int i)
- {
- str.Sort();
- for(intk =0; k < str.Count; k++)
- {
- strings = str[k];
- if(Convert.ToString(i) == s)
- return "Open";
- }
- return "Closed";
- }
- public stringService(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 voidScan(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
来源: http://www.cnblogs.com/kmust/p/6685752.html