近幾年工作經常使用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++) { //---------------------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 -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"; //---------------------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 + 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()); } }
好了,大家最後,可能都會說,我不想設計,也不想開發,我想要現成的怎麼辦?當然了,最後附上程式,大家可以實際進行測試使用。
工具連結:http://download.csdn.net/detail/dwx1005526886/9808540