近幾年工作經常使用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
轉載于:https://www.cnblogs.com/kmust/p/6685752.html