C#實(shí)現(xiàn)網(wǎng)絡(luò)小程序的步驟詳解
經(jīng)常要檢測(cè)某些IP地址范圍段的計(jì)算機(jī)是否在線。
有很多的方法,比如進(jìn)入到網(wǎng)關(guān)的交換機(jī)上去查詢、使用現(xiàn)成的工具或者編寫一個(gè)簡(jiǎn)單的DOS腳本等等,這些都比較容易實(shí)現(xiàn)。
現(xiàn)在使用C#來完成。
1、簡(jiǎn)單上手
公用函數(shù):
public static long IPToLong(string ip) { //將IP地址轉(zhuǎn)換為長(zhǎng)整數(shù) string[] ipBytes = ip.Split('.'); long ipLong = 0; ipLong += long.Parse(ipBytes[0]) * 256 * 256 * 256; ipLong += long.Parse(ipBytes[1]) * 256 * 256; ipLong += long.Parse(ipBytes[2]) * 256; ipLong += long.Parse(ipBytes[3]); return ipLong; } public static string LongToIP(long ip) { //將長(zhǎng)整數(shù)IP地址轉(zhuǎn)換為實(shí)際的IP地址 long ipLong = ip; string ipString = string.Empty; ipString += ipLong / 256 / 256 / 256 + "."; ipLong = ipLong % (256 * 256 * 256); ipString += ipLong / 256 / 256 + "."; ipLong = ipLong % (256 * 256); ipString += ipLong / 256 + "."; ipLong = ipLong % 256; ipString += ipLong; return ipString; }
點(diǎn)擊【檢測(cè)】按鈕:
DateTime startTime, endTime; startTime= DateTime.Now; listBox1.Items.Add(startTime.ToString()); string startIP = textBox1.Text; string endIP = textBox2.Text; // 將起始IP地址和結(jié)束IP地址轉(zhuǎn)換為長(zhǎng)整數(shù) long startIPLong = IPToLong(startIP); long endIPLong = IPToLong(endIP); Ping ping = new Ping(); // 遍歷IP地址范圍 for (long i = startIPLong; i <= endIPLong; i++) { // 將整數(shù)轉(zhuǎn)換為IP地址 string ip = LongToIP(i); // 輸出 PingReply pingReply = ping.Send(ip); if (pingReply.Status == IPStatus.Success) { listBox1.Items.Add( ip + "=>計(jì)算機(jī)在線"); } else { listBox1.Items.Add(ip); } } endTime = DateTime.Now; listBox1.Items.Add(endTime.ToString()); listBox1.Items.Add("OK:" + (endTime - startTime).ToString());
執(zhí)行時(shí)沒有問題的,可以出來結(jié)果,問題是界面卡頓了。
執(zhí)行的時(shí)間也很長(zhǎng),執(zhí)行需要1分21秒。
這個(gè)結(jié)果不能接受,需要對(duì)程序加以改進(jìn)。
2、使用并行計(jì)算
不需要改動(dòng)公用代碼,只需要改動(dòng)檢測(cè)部分。
Dictionary<string, string> ipResults = new Dictionary<string, string>(); DateTime startTime, endTime; startTime = DateTime.Now; listBox1.Items.Add(startTime.ToString()); string startIP = textBox1.Text; string endIP = textBox2.Text; // 將起始IP地址和結(jié)束IP地址轉(zhuǎn)換為整數(shù) long startIPLong = IPToLong(startIP); long endIPLong = IPToLong(endIP); // 創(chuàng)建一個(gè)可以存儲(chǔ)IP地址的List List<string> ipList = new List<string>(); for (long i = startIPLong; i <= endIPLong; i++) { // 將整數(shù)轉(zhuǎn)換為IP地址 string ip = LongToIP(i); ipList.Add(ip); ipResults.Add(ip,""); listBox1.Items.Add(ip); } // 開啟并行計(jì)算 Parallel.ForEach(ipList, (ip) => { // 創(chuàng)建一個(gè)新的Ping類 Ping pingSender = new Ping(); // 發(fā)送一個(gè)Ping請(qǐng)求 var reply = pingSender.Send(ip); // 如果返回的狀態(tài)是Success,則IP地址在線 if (reply.Status == IPStatus.Success) { ipResults[ip] = "在線"; ChangeIPStatus(ip,"在線"); } else { ipResults[ip] = "NO"; ChangeIPStatus(ip, "NO"); } }); endTime = DateTime.Now; listBox1.Items.Add(endTime.ToString()); listBox1.Items.Add("OK:" + (endTime - startTime).ToString());
增加一個(gè)公用函數(shù):
public void ChangeIPStatus(string ip,string S1) { // 定位到listbox中記錄并更改IP是否在線 int index = listBox1.Items.IndexOf(ip); listBox1.Items[index] = ip+" "+S1; }
出現(xiàn)問題:
⑴ 提示“C#線程間操作無效:從不是創(chuàng)建控件“textbox1”的線程訪問它”,這個(gè)就簡(jiǎn)單設(shè)置Control.CheckForIllegalCrossThreadCalls=false即可解決;
⑵ 提示“listbox1包含的項(xiàng)太多”,這個(gè)是不是與并行計(jì)算開啟的線程太多有關(guān)?考慮到本機(jī)是8核,保守一點(diǎn),修改參數(shù)
Parallel.ForEach(ipList, new ParallelOptions() { MaxDegreeOfParallelism = MaxDegreeOfParallelism = Environment.ProcessorCount }, (ip) => { //執(zhí)行代碼 }
程序可以正常運(yùn)行了。
⑶ 界面依然阻塞,但用時(shí)更多了。
去ping255個(gè)地址,竟然用了12分32秒!??!這個(gè)真是不可忍受,最關(guān)鍵沒有界面交互,這太不用戶友好了!
3、添加異步編程
Dictionary<string, string> ipResults = new Dictionary<string, string>(); DateTime startTime, endTime; startTime = DateTime.Now; listBox1.Items.Add(startTime.ToString()); string startIP = textBox1.Text; string endIP = textBox2.Text; // 將起始IP地址和結(jié)束IP地址轉(zhuǎn)換為整數(shù) long startIPLong = IPToLong(startIP); long endIPLong = IPToLong(endIP); // 創(chuàng)建一個(gè)可以存儲(chǔ)IP地址的List List<string> ipList = new List<string>(); for (long i = startIPLong; i <= endIPLong; i++) { // 將整數(shù)轉(zhuǎn)換為IP地址 string ip = LongToIP(i); ipList.Add(ip); ipResults.Add(ip,""); listBox1.Items.Add(ip); } Task task = new Task(() => { // 創(chuàng)建一個(gè)多線程 Parallel.ForEach(ipList, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (ip) => { // 創(chuàng)建一個(gè)新的Ping類 Ping pingSender = new Ping(); // 發(fā)送一個(gè)Ping請(qǐng)求 var reply = pingSender.Send(ip); if (reply.Status == IPStatus.Success) { listBox1.Invoke(new Action(() => { int index = listBox1.Items.IndexOf(ip); listBox1.Items[index] = ip + " " + "在線"; })); } else { listBox1.Invoke(new Action(() => { int index = listBox1.Items.IndexOf(ip); listBox1.Items[index] = ip + " " + "NO"; })); } }); }); task.Start(); Task.WaitAll(); endTime = DateTime.Now; listBox1.Items.Add(endTime.ToString()); listBox1.Items.Add("OK:" + (endTime - startTime).ToString());
好了,因?yàn)槭褂肨ask異步編程,界面也不再阻塞和卡頓了,不過運(yùn)行多少時(shí)間不能準(zhǔn)確得到,改動(dòng)一下代碼,就是將時(shí)間輸出定位到任務(wù)完成:
task.ContinueWith((t) => { endTime = DateTime.Now; listBox1.Items.Add(endTime.ToString()); listBox1.Items.Add("OK:" + (endTime - startTime).ToString()); });
運(yùn)行時(shí)間為1分41秒,界面不卡頓了。
可是運(yùn)行仍然是逐個(gè)IP地址在ping,根本沒有并行計(jì)算的效果。雖然使用了Parallel.ForEach,可能是由于線程需要等待導(dǎo)致資源開銷過大,那么線程沒有被有效地利用。
這其實(shí)與普通的使用線程來做沒有什么區(qū)別了。
4、補(bǔ)充
⑴ 檢測(cè)方法:
string ipAddress = (string)obj; TcpClient client = new TcpClient(); try { client.Connect(ipAddress, 80); //在線 } catch (Exception ex) { //不在線 } finally { client.Close(); }
引用:
using System.Net.Sockets;
⑵ 檢測(cè)輸入的IP地址是否合法:
IPAddress address; if (IPAddress.TryParse(ipAddress, out address)) { // 檢查IP地址是否為IPv4地址 if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) return true; }else{ return false; }
對(duì)于檢測(cè)計(jì)算機(jī)在線與否沒有好的方法?看那么多的網(wǎng)絡(luò)小工具,肯定有!
先完成這個(gè)效果,后面再進(jìn)行優(yōu)化。
到此這篇關(guān)于C#實(shí)現(xiàn)網(wǎng)絡(luò)小程序的步驟詳解的文章就介紹到這了,更多相關(guān)C#網(wǎng)絡(luò)小程序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#模擬鏈表數(shù)據(jù)結(jié)構(gòu)的實(shí)例解析
這篇文章主要介紹了C#模擬鏈表數(shù)據(jù)結(jié)構(gòu)的實(shí)例解析,包括隊(duì)雙向鏈表的模擬方法,例子中隊(duì)鏈表的操作也有很好的說明,需要的朋友可以參考下2016-04-04C#開發(fā)WinForm項(xiàng)目實(shí)現(xiàn)HTML編輯器
這篇文章介紹了C#開發(fā)WinForm項(xiàng)目實(shí)現(xiàn)HTML編輯器的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06C#利用XML創(chuàng)建Excel文檔的實(shí)現(xiàn)方法
這篇文章主要介紹了C#利用XML創(chuàng)建Excel文檔的實(shí)現(xiàn)方法,需要的朋友可以參考下2014-08-08C#中比較常用的DateTime結(jié)構(gòu)的使用方法
這篇文章主要介紹了C#中比較常用的DateTime結(jié)構(gòu)的使用方法,需要的朋友可以參考下2015-11-11