C#實現(xiàn)網(wǎng)絡(luò)小程序的步驟詳解
經(jīng)常要檢測某些IP地址范圍段的計算機是否在線。
有很多的方法,比如進入到網(wǎng)關(guān)的交換機上去查詢、使用現(xiàn)成的工具或者編寫一個簡單的DOS腳本等等,這些都比較容易實現(xiàn)。
現(xiàn)在使用C#來完成。
1、簡單上手
公用函數(shù):
public static long IPToLong(string ip)
{
//將IP地址轉(zhuǎn)換為長整數(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)
{
//將長整數(shù)IP地址轉(zhuǎn)換為實際的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;
}點擊【檢測】按鈕:
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);
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 + "=>計算機在線");
}
else
{
listBox1.Items.Add(ip);
}
}
endTime = DateTime.Now;
listBox1.Items.Add(endTime.ToString());
listBox1.Items.Add("OK:" + (endTime - startTime).ToString());執(zhí)行時沒有問題的,可以出來結(jié)果,問題是界面卡頓了。

執(zhí)行的時間也很長,執(zhí)行需要1分21秒。
這個結(jié)果不能接受,需要對程序加以改進。
2、使用并行計算
不需要改動公用代碼,只需要改動檢測部分。
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)建一個可以存儲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);
}
// 開啟并行計算
Parallel.ForEach(ipList, (ip) =>
{
// 創(chuàng)建一個新的Ping類
Ping pingSender = new Ping();
// 發(fā)送一個Ping請求
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());增加一個公用函數(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”的線程訪問它”,這個就簡單設(shè)置Control.CheckForIllegalCrossThreadCalls=false即可解決;
⑵ 提示“listbox1包含的項太多”,這個是不是與并行計算開啟的線程太多有關(guān)?考慮到本機是8核,保守一點,修改參數(shù)
Parallel.ForEach(ipList, new ParallelOptions() { MaxDegreeOfParallelism = MaxDegreeOfParallelism = Environment.ProcessorCount }, (ip) =>
{
//執(zhí)行代碼
}
程序可以正常運行了。
⑶ 界面依然阻塞,但用時更多了。

去ping255個地址,竟然用了12分32秒?。。∵@個真是不可忍受,最關(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)建一個可以存儲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)建一個多線程
Parallel.ForEach(ipList, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (ip) =>
{
// 創(chuàng)建一個新的Ping類
Ping pingSender = new Ping();
// 發(fā)送一個Ping請求
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());好了,因為使用Task異步編程,界面也不再阻塞和卡頓了,不過運行多少時間不能準確得到,改動一下代碼,就是將時間輸出定位到任務(wù)完成:
task.ContinueWith((t) =>
{
endTime = DateTime.Now;
listBox1.Items.Add(endTime.ToString());
listBox1.Items.Add("OK:" + (endTime - startTime).ToString());
});
運行時間為1分41秒,界面不卡頓了。
可是運行仍然是逐個IP地址在ping,根本沒有并行計算的效果。雖然使用了Parallel.ForEach,可能是由于線程需要等待導(dǎo)致資源開銷過大,那么線程沒有被有效地利用。
這其實與普通的使用線程來做沒有什么區(qū)別了。
4、補充
⑴ 檢測方法:
string ipAddress = (string)obj;
TcpClient client = new TcpClient();
try
{
client.Connect(ipAddress, 80);
//在線
}
catch (Exception ex)
{
//不在線
}
finally
{
client.Close();
}引用:
using System.Net.Sockets;
⑵ 檢測輸入的IP地址是否合法:
IPAddress address;
if (IPAddress.TryParse(ipAddress, out address))
{
// 檢查IP地址是否為IPv4地址
if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
return true;
}else{
return false;
}
對于檢測計算機在線與否沒有好的方法?看那么多的網(wǎng)絡(luò)小工具,肯定有!
先完成這個效果,后面再進行優(yōu)化。
到此這篇關(guān)于C#實現(xiàn)網(wǎng)絡(luò)小程序的步驟詳解的文章就介紹到這了,更多相關(guān)C#網(wǎng)絡(luò)小程序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用C#實現(xiàn)讀取系統(tǒng)配置文件的代碼實例講解
這篇文章主要介紹了使用C#實現(xiàn)讀取系統(tǒng)配置文件的代碼實例,使用到了ConfigurationManager類,需要的朋友可以參考下2015-12-12
關(guān)于C#調(diào)用C++dll傳指針釋放內(nèi)存問題
這篇文章主要介紹了關(guān)于C#調(diào)用C++dll傳指針釋放內(nèi)存問題,本文給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
C#基礎(chǔ)語法:結(jié)構(gòu)和類區(qū)別詳解
這篇文章主要介紹了C#基礎(chǔ)語法:結(jié)構(gòu)和類詳解,本文總結(jié)了一些結(jié)構(gòu)和類的不同之處并給出了測試區(qū)別特性代碼,需要的朋友可以參考下2015-06-06
C#通過oledb訪問access數(shù)據(jù)庫的方法
這篇文章主要介紹了C#通過oledb訪問access數(shù)據(jù)庫的方法,實例分析了C#操作access數(shù)據(jù)庫的相關(guān)技巧,需要的朋友可以參考下2015-06-06

