前言:懶人可以直接往下看,有代碼和全部資源可以下載。此文章是先前文章的修改版,主要是將代碼中的配置項放置到了app.config文件中,方便修改。未經許可請勿轉載,如有疑問,請聯系作者:yxxrui@163.com
我遇到的問題:公司的網絡沒有固定的公網IP地址,但是需要能夠保證的是,每次動態分配的IP地址均為獨立的公網IP,只是每次分配后會在1-2天后更換,或者重啟路由器后更換,為了能夠把這個公網IP利用起來,大家常用的是使用花生殼之類的軟件來操作,我使用過花生殼的多款產品,挺好的,就是有一下幾個缺點:
1、需要使用花生殼上購買的域名才行,或者使用免費的殼域名,其丑無比
2、不穩定,也很慢
3、限制流量,超流量需要收費
4、限制端口,特定端口需要收費
5、需要在電腦上運行一個花生殼的軟件
解決方案:但是為了解決問題,我開始摸索自己搞定它,公司域名從阿里云上購買,阿里云提供云解析技術免費版,提供通過api來管理域名的功能,當我看到該文檔的時候直接就看到了希望,解決起來絕對沒問題了。首先需要確認一下,有兩種情況:
1、公司服務器直接接入網線,這個時候服務器的IP就是公網IP
2、公司服務器鏈接公司路由器,路由器鏈接網線,這個時候路由器上是公網IP,而服務器上是局域網IP
第一種情況最簡單了,不需要設置什么了,第二種情況需要到路由器設置界面設置端口轉發或者直接將全部端口映射到內網的服務器IP上,這樣的話,訪問公網IP的某個端口時相當于訪問內網IP的映射端口,比如路由器IP為125.120.83.30,內網IP為192.168.168.168。可以將路由器中80端口映射到192.168.168.168的80端口上。
到阿里云控制臺申請accessKeyId和accessKeySecret,用來調用API的,為了簡單起見,先給域名添加一條解析記錄,這樣就不需要在程序里判斷該域名是否已創建,然后可以直接修改解析記錄了。比如我的域名為yxxrui.cn,記錄值為blog,也就是要把子域名blog.yxxrui.cn指向我自己電腦125.120.83.30上。
下邊直接貼出代碼:
using System;
using System.Configuration;
using System.Net;
using System.Text;
using Aliyun.Acs.Alidns.Model.V20150109;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
namespace AliyunDomain
{
class Program
{
private static readonly string RegionId=GetConfig("regionId");
private static readonly string AccessKeyId=GetConfig("accessKeyId");
private static readonly string AccessKeySecret=GetConfig("accessKeySecret");
private static string _recordId = GetConfig("recordId");
private static readonly string Domain = GetConfig("domain");
private static readonly string Rr = GetConfig("rr");
private static readonly IClientProfile ClientProfile =
DefaultProfile.GetProfile(RegionId, AccessKeyId,AccessKeySecret);
private static readonly IAcsClient Client = new DefaultAcsClient(ClientProfile);
static void Main(string[] args)
{
if (string.IsNullOrWhiteSpace(_recordId))
{
//如果沒有獲取過,那么獲取一下,然后保存起來
_recordId = GetRecordId(Domain, Rr);
SaveConfig("recordId",_recordId);
}
if (_recordId == "") return;
//獲取成功,并且有變化時
string lastIp = GetConfig("lastIP");
string curIp = GetIp();
if (!curIp.Equals("") && !lastIp.Equals(curIp))
{
var request = new UpdateDomainRecordRequest
{
RecordId = _recordId,
RR = Rr,
Type = "A",
Value = curIp,
TTL = 600,
Priority = 10
};
Client.DoAction(request);
SaveConfig("lastIP", curIp);
}
}
#region 保存配置信息
/// <summary>
/// 保存配置信息
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
private static void SaveConfig(string name,string value)
{
var cfa = ReadAppConfig();
cfa.AppSettings.Settings[name].Value = value;
cfa.Save();
}
#endregion
#region 獲取配置項
/// <summary>
/// 獲取配置項
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private static string GetConfig(string name)
{
var cfa = ReadAppConfig();
return cfa.AppSettings.Settings[name].Value;
}
#endregion
#region 調用阿里云接口獲取域名的唯一記錄ID
/// <summary>
/// 調用阿里云接口獲取域名的唯一記錄ID
/// </summary>
/// <param name="domain">域名</param>
/// <param name="rr">子域名</param>
/// <returns></returns>
private static string GetRecordId(string domain,string rr)
{
DescribeDomainRecordsRequest reqq = new DescribeDomainRecordsRequest
{
DomainName = domain,
RRKeyWord = rr
};
var rss = Client.GetAcsResponse(reqq);
foreach (var record in rss.DomainRecords)
{
if (record.DomainName.Equals(domain) && record.RR.Equals(rr))
{
return record.RecordId;
}
}
return "";
}
#endregion
#region 獲取公網IP
/// <summary>
/// 獲取當前電腦的真實外網IP地址,可以自行修改成穩定的
/// </summary>
/// <returns></returns>
private static string GetIp()
{
string ip = "";
try
{
//獲取或設置用于向Internet資源的請求進行身份驗證的網絡憑據
WebClient myWebClient = new WebClient {
Credentials = CredentialCache.DefaultCredentials };
//從指定網站下載數據
Byte[] pageData = myWebClient.DownloadData(
"
//如果獲取網站頁面采用的是GB2312,則使用這句
string pageHtml = Encoding.Default.GetString(pageData);
//如果獲取網站頁面采用的是UTF-8,則使用這句
//string pageHtml = Encoding.UTF8.GetString(pageData);
return pageHtml;
}
catch (WebException webEx)
{
}
return ip;
}
#endregion
#region 獲取配置文件
private static Configuration _config;
private static Configuration ReadAppConfig()
{
if (_config == null)
{
string configPath = @"app.config";
_config = ConfigurationManager.OpenMappedExeConfiguration(
new ExeConfigurationFileMap()
{
ExeConfigFilename = configPath
}, ConfigurationUserLevel.None);
}
//MessageBox.Show(config.AppSettings.Settings["serverIp"].Value);
return _config;
}
#endregion
}
}
app.config文件內容如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<appSettings>
<!--作者:楊浩瑞,博客:http://www.yxxrui.cn -->
<!-- ############################################## -->
<!--區域-->
<!--阿里云accessKeyId-->
<!--阿里云accessKeySecret-->
<!--記錄ID,需注意,如果您修改了其他配置,不確定recordId是什么
那么一定要置為空值,系統會自動獲取的-->
<!--您的域名,比如:yxxrui.cn-->
<!--您的子域名,比如:blog-->
<!--您的服務器上次的IP地址,用來緩存,您無需修改-->
<add key="regionId" value="cn-hangzhou"/>
<add key="accessKeyId" value="LTAIYkLo123456"/>
<add key="accessKeySecret" value="WXXfo55OshQC4ZB789456123130"/>
<add key="recordId" value=""/>
<add key="domain" value="yxxrui.cn"/>
<add key="rr" value="blog"/>
<add key="lastIP" value="36.24.222.133"/>
</appSettings>
</configuration>
為了更好的獲取IP地址,我專門寫了一個簡單頁面,訪問該頁面后返回您的外網IP
http://www.yxxrui.cn/yxxrui_cabangs_api/myip.ashx
本代碼為C#代碼,建議將項目設置為winform程序,不要設置為控制臺程序,否則每次執行時會彈出黑色的控制臺,很惡心人的。該代碼未實現自動檢測和執行(如需程序創建計劃任務,可聯系我),只是做了以下工作:
1、獲取當前電腦真實公網IP
2、查看當前IP是否有變化
3、若無變化直接退出,若有變化則修改域名解析設置
這些并不能達到實時解析。但可以通過使用window 操作系統中的任務計劃程序,制定計劃,每(1)分鐘執行該軟件一次即可。
1、編譯好的可執行包請直接下載:
附件:動態域名解析.zip
2、需要引入阿里云提供的SDK(我已編譯好了):
附件:阿里云域名解析SDK.zip
3、獲取IP地址的代碼,myip.ashx,需要.net環境的服務器(如IIS):
附件:myip.zip
4、此項目完整的源代碼,可以自行修改和編譯成需要的功能(VS2013旗艦版):
附件:動態域名解析源代碼.zip