C#如何自動(dòng)選擇出系統(tǒng)中最合適的IP地址
寫這個(gè)是因?yàn)楹荛L(zhǎng)時(shí)間以來(lái),碰到過(guò)很多次這個(gè)問(wèn)題,但都沒(méi)當(dāng)回事,這次又碰到了這個(gè)老問(wèn)題,無(wú)奈百度了一圈兒未果,身邊又沒(méi)有大??梢哉?qǐng)教,就自己先“總結(jié)”了一套方法,一來(lái)給自己記錄,二來(lái)如果碰巧能有朋友看到并為他解決了同樣的困擾我將感到很爽。
起因:凡是網(wǎng)絡(luò)程序,Coder似乎不可避免要碰到,你的代碼如何在不同的機(jī)器上挑選出最合適的那個(gè)IP來(lái)通訊,因?yàn)槿绻蜷_一個(gè)應(yīng)用程序讓用戶來(lái)選擇用哪個(gè)IP地址和端口來(lái)通訊似乎就代表著這是個(gè)多么低端的程序,多么低能的程序員,所以一定要自動(dòng)選擇,用戶 0 感知,就像偉大的QQ那樣。我也再次碰到了這個(gè)事情,Q群未果百度未果,就自己用 Framework 中提供的方法和屬性,自己總結(jié)了一個(gè)“規(guī)則”,下面直奔主題。
現(xiàn)在的機(jī)器可能是雙網(wǎng)卡,可能因?yàn)楦黝愜浖万?qū)動(dòng)又有多個(gè)虛擬網(wǎng)卡,所以我的“規(guī)則”是不直接判斷 IP 是不是符合規(guī)定,而是先從 NetworkInterface 入手,下面總結(jié)一下:
1. 獲取所有本地 NetworkInterface 對(duì)象;
2. 其屬性 Type 最好為 Wireless80211、Ethernet、Fddi、Ppp等,因?yàn)楦鶕?jù) MSDN 的解釋這幾類會(huì)是普通家用電腦常見的接口類型,但這樣判斷不太準(zhǔn)確,所以只作為輔助判斷條件;
3. 其屬性 OperationalStatus 應(yīng)該為 Up,根據(jù) MSDN 解釋,僅在 Up 時(shí)表示該網(wǎng)絡(luò)接口是可以正常收發(fā)數(shù)據(jù)的,這也可以作為判斷網(wǎng)卡(網(wǎng)絡(luò))是否可用的一個(gè)條件;
4. 使用 GetIPProperties().UnicastAddresses 方法,獲取該網(wǎng)絡(luò)接口下所有單播地址,這可以讓你獲得網(wǎng)絡(luò)IP;
5. 該IP的DuplicateAddressDetectionState屬性應(yīng)該為 Preferred,表示地址有效,即IP地址可正常使用;
6. 該IP的屬性 PrefixOrigin 其值應(yīng)該為 Dhcp 或 Manual,表示IP前綴由 Dhcp 分配或手動(dòng)指定;
7. 該IP的屬性 SuffixOrigin 其值應(yīng)該為 OriginDhcp 或 Manual,表示IP后綴由 DHCP 分配或手動(dòng)指定;
綜上所述,基本可以排除一些如 169 、127.0.0.1 等此類的特殊地址,還有一些亂七八糟不知有什么用的網(wǎng)絡(luò)接口(有的網(wǎng)絡(luò)接口沒(méi)有地址,有的只有IPV6地址),但我感覺我這方法應(yīng)該不是個(gè)“正路”,希望能有有經(jīng)驗(yàn)的人看到給我指點(diǎn)迷津。
以下貼出測(cè)試用的截圖和代碼,是我機(jī)器上的結(jié)果:

代碼:
var interfaceList = NetworkInterface.GetAllNetworkInterfaces();
StringBuilder sb = new StringBuilder(512);
int index = 0;
string message = string.Empty;
foreach(var item in interfaceList)
{
index++;
sb.AppendLine(string.Format("Interface{0}: {1}", index, item.Name));
sb.AppendLine(string.Format("Description: {0}", item.Description));
sb.AppendLine(string.Format("ID: {0}", item.Id));
sb.AppendLine(string.Format("Type: {0}", item.NetworkInterfaceType));
sb.AppendLine(string.Format("OperationalStatus: {0}", item.OperationalStatus));
sb.AppendLine(string.Format("IsReceiveOnly: {0}", item.IsReceiveOnly));
sb.AppendLine(string.Format("Speed: {0}", item.Speed));
sb.AppendLine(string.Format("SupportMulticast: {0}", item.SupportsMulticast));
sb.AppendLine(string.Format("SupportIPV4: {0}", item.Supports(NetworkInterfaceComponent.IPv4)));
sb.AppendLine(string.Format("IP Properties:"));
var addresses = item.GetIPProperties().UnicastAddresses;
int j = 0;
foreach (var ip in addresses)
{
j++;
sb.AppendLine(string.Format("Address{0}: {1}({2})", j, ip.Address.ToString(),ip.Address.AddressFamily));
sb.AppendLine(string.Format("IPV4 Mask: {0}", ip.IPv4Mask));
sb.AppendLine(string.Format("PrefixOrigin: {0}", ip.PrefixOrigin));
sb.AppendLine(string.Format("SuffixOrigin: {0}", ip.SuffixOrigin));
sb.AppendLine(string.Format("DuplicateAddressDetectionState: {0}", ip.DuplicateAddressDetectionState));
}
sb.AppendLine();
}
textBox1.Text = sb.ToString();
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
相關(guān)文章
C# winfrom 模擬ftp文件管理實(shí)現(xiàn)代碼
從網(wǎng)上找到的非常好用的模擬ftp管理代碼,整理了一下,希望對(duì)需要的人有幫助2014-01-01
C#實(shí)現(xiàn)獲取電腦硬件顯卡信息的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)獲取電腦硬件顯卡信息,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
基于WPF簡(jiǎn)單實(shí)現(xiàn)Meesage消息提醒
這篇文章主要介紹了如何利用WPF簡(jiǎn)單實(shí)現(xiàn)Meesage消息提醒,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,需要的可以參考一下2023-07-07
C#基于JsonConvert解析Json數(shù)據(jù)的方法實(shí)例
最近初接觸C#語(yǔ)言,發(fā)現(xiàn)JSON解析這塊和JAVA差異過(guò)大,下面這篇文章主要給大家介紹了關(guān)于C#基于JsonConvert解析Json數(shù)據(jù)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04
使用C#寫了一個(gè)可以推算火車票身份證號(hào)碼的小程序
這篇文章主要介紹了使用C#寫了一個(gè)可以推算火車票身份證號(hào)碼的小程序 的相關(guān)資料,需要的朋友可以參考下2016-02-02
C#日期格式字符串的相互轉(zhuǎn)換操作實(shí)例分析
這篇文章主要介紹了C#日期格式字符串的相互轉(zhuǎn)換操作,結(jié)合實(shí)例形式分析了C#日期格式字符串的相互轉(zhuǎn)換操作函數(shù)與相關(guān)使用技巧,需要的朋友可以參考下2019-08-08

