[點(diǎn)晴永久免費(fèi)OA]C#利用阿里云云解析API實(shí)現(xiàn)動(dòng)態(tài)域名解析(ddns)【含可執(zhí)行文件和源碼】
前言:懶人可以直接往下看,有代碼和全部資源可以下載。此文章是先前文章的定時(shí)版,主要是添加了定時(shí)執(zhí)行的功能,并且將代碼中的配置項(xiàng)放置到了app.config文件中,方便不懂開(kāi)發(fā)的朋友修改使用。 遇到的問(wèn)題:公司的網(wǎng)絡(luò)沒(méi)有固定的公網(wǎng)IP地址,但是需要能夠保證的是,每次動(dòng)態(tài)分配的IP地址均為獨(dú)立的公網(wǎng)IP,只是每次分配后會(huì)在1-2天后更換,或者重啟路由器后更換,為了能夠把這個(gè)公網(wǎng)IP利用起來(lái),大家常用的是使用花生殼之類的軟件來(lái)操作,使用過(guò)花生殼的多款產(chǎn)品,挺好的,就是有一下幾個(gè)缺點(diǎn): 1、需要使用花生殼上購(gòu)買的域名才行,或者使用免費(fèi)的殼域名,其丑無(wú)比 2、不穩(wěn)定,也很慢 3、限制流量,超流量需要收費(fèi) 4、限制端口,特定端口需要收費(fèi) 5、需要在電腦上運(yùn)行一個(gè)花生殼的軟件 解決方案:但是為了解決問(wèn)題,開(kāi)始摸索自己搞定它,公司域名從阿里云上購(gòu)買,阿里云提供云解析技術(shù)免費(fèi)版,提供通過(guò)api來(lái)管理域名的功能,當(dāng)我看到該文檔的時(shí)候直接就看到了希望,解決起來(lái)絕對(duì)沒(méi)問(wèn)題了。首先需要確認(rèn)一下,有兩種情況: 1、公司服務(wù)器直接接入網(wǎng)線,這個(gè)時(shí)候服務(wù)器的IP就是公網(wǎng)IP 2、公司服務(wù)器鏈接公司路由器,路由器鏈接網(wǎng)線,這個(gè)時(shí)候路由器上是公網(wǎng)IP,而服務(wù)器上是局域網(wǎng)IP 第一種情況最簡(jiǎn)單了,不需要設(shè)置什么了,第二種情況需要到路由器設(shè)置界面設(shè)置端口轉(zhuǎn)發(fā)或者直接將全部端口映射到內(nèi)網(wǎng)的服務(wù)器IP上,這樣的話,訪問(wèn)公網(wǎng)IP的某個(gè)端口時(shí)相當(dāng)于訪問(wèn)內(nèi)網(wǎng)IP的映射端口,比如路由器IP為125.120.83.30,內(nèi)網(wǎng)IP為192.168.168.168??梢詫⒙酚善髦?0端口映射到192.168.168.168的80端口上。 到阿里云控制臺(tái)申請(qǐng)accessKeyId和accessKeySecret,用來(lái)調(diào)用API的,為了簡(jiǎn)單起見(jiàn),先給域名添加一條解析記錄,這樣就不需要在程序里判斷該域名是否已創(chuàng)建,然后可以直接修改解析記錄了。比如我的域名為yxxrui.cn,記錄值為blog,也就是要把子域名blog.yxxrui.cn指向我自己電腦125.120.83.30上。 下邊直接貼出代碼: 創(chuàng)建window service用于定時(shí)執(zhí)行解析任務(wù),在Service的OnStart方法中添加: MainProgram.MyTimerTask(); 其中MainProgram.cs為: 1 using System; 2 using System.Configuration; 3 using System.Net; 4 using System.Text; 5 using System.Text.RegularExpressions; 6 using System.Threading; 7 using Aliyun.Acs.Alidns.Model.V20150109; 8 using Aliyun.Acs.Core; 9 using Aliyun.Acs.Core.Profile; 10 11 namespace AliyunDynamicDomain 12 { 13 /// <summary> 14 /// 修改時(shí)間:2018-11-18 15 /// 為了方便,特意改寫為window service,按時(shí)刷新任務(wù) 16 /// 不再需要手動(dòng)設(shè)置window自帶的定時(shí)任務(wù) 17 /// 作者:楊浩瑞 yxxrui@163.com 18 /// </summary> 19 class MainProgram 20 { 21 #region 獲取基本參數(shù)和類屬性 22 private static readonly string RegionId = GetConfig("regionId"); 23 private static readonly string AccessKeyId = GetConfig("accessKeyId"); 24 private static readonly string AccessKeySecret = GetConfig("accessKeySecret"); 25 private static string _recordId = GetConfig("recordId"); 26 private static readonly string Domain = GetConfig("domain"); 27 private static readonly string Rr = GetConfig("rr"); 28 private static readonly string IpServer = GetConfig("IpServer"); 29 private static int _ttl = 600; 30 private static int _waitTime = 60; 31 private static readonly IClientProfile ClientProfile = DefaultProfile.GetProfile(RegionId, AccessKeyId, 32 AccessKeySecret); 33 private static readonly IAcsClient Client = new DefaultAcsClient(ClientProfile); 34 35 private static readonly object TimerLocker = new object(); 36 private static Timer _myTimer; 37 #endregion 38 39 #region 定時(shí)任務(wù) 40 public static void MyTimerTask() 41 { 42 if (!int.TryParse(GetConfig("TTL"), out _ttl)) 43 { 44 _ttl = 600; 45 } 46 if (!int.TryParse(GetConfig("WaitTime"), out _waitTime)) 47 { 48 _waitTime = 60; 49 } 50 if (_myTimer != null) 51 { 52 return; 53 } 54 lock (TimerLocker) 55 { 56 if (_myTimer == null) 57 { 58 //第一次開(kāi)始的時(shí)間,1秒后開(kāi)始執(zhí)行 59 var startTime = DateTime.Now.AddSeconds(1); 60 var delayTime = (startTime - DateTime.Now); 61 var intervalTime = new TimeSpan(0, 0, 0, _waitTime); //10秒執(zhí)行一次 62 TimerCallback timerDelegate = DealFun; 63 _myTimer = new Timer(timerDelegate, null, delayTime, intervalTime); 64 } 65 } 66 } 67 #endregion 68 69 #region 執(zhí)行程序,解析域名 70 71 public static void DealFun(object obj) 72 { 73 try 74 { 75 if (string.IsNullOrWhiteSpace(_recordId)) 76 { 77 //如果沒(méi)有獲取過(guò),那么獲取一下,然后保存起來(lái) 78 _recordId = GetRecordId(Domain, Rr); 79 SaveConfig("recordId", _recordId); 80 } 81 if (string.IsNullOrWhiteSpace(_recordId)) 82 { 83 LogHelper.Error("recordId獲取失敗"); 84 return; 85 } 86 //獲取成功,并且有變化時(shí) 87 string lastIp = GetConfig("lastIP"); 88 string curIp = GetIp(); 89 if (!curIp.Equals("") && !lastIp.Equals(curIp)) 90 { 91 var request = new UpdateDomainRecordRequest 92 { 93 RecordId = _recordId, 94 RR = Rr, 95 Type = "A", 96 Value = curIp, 97 TTL = _ttl, 98 Priority = 10 99 }; 100 Client.DoAction(request); 101 SaveConfig("lastIP", curIp); 102 LogHelper.Info("刷新成功"); 103 return; 104 } 105 LogHelper.Info("與上次IP一致,無(wú)需刷新:" + curIp); 106 } 107 catch (Exception e) 108 { 109 LogHelper.Error(e.ToString()); 110 } 111 } 112 113 #endregion 114 115 #region 保存配置信息 116 /// <summary> 117 /// 保存配置信息 118 /// </summary> 119 /// <param name="name"></param> 120 /// <param name="value"></param> 121 private static void SaveConfig(string name,string value) 122 { 123 var cfa = ReadAppConfig(); 124 cfa.AppSettings.Settings[name].Value = value; 125 cfa.Save(); 126 } 127 #endregion 128 129 #region 獲取配置項(xiàng) 130 /// <summary> 131 /// 獲取配置項(xiàng) 132 /// </summary> 133 /// <param name="name"></param> 134 /// <returns></returns> 135 private static string GetConfig(string name) 136 { 137 try 138 { 139 var cfa = ReadAppConfig(); 140 return cfa.AppSettings.Settings[name].Value; 141 } 142 catch 143 { 144 return ""; 145 } 146 } 147 #endregion 148 149 #region 調(diào)用阿里云接口獲取域名的唯一記錄ID 150 /// <summary> 151 /// 調(diào)用阿里云接口獲取域名的唯一記錄ID 152 /// </summary> 153 /// <param name="domain">域名</param> 154 /// <param name="rr">子域名</param> 155 /// <returns></returns> 156 private static string GetRecordId(string domain,string rr) 157 { 158 DescribeDomainRecordsRequest reqq = new DescribeDomainRecordsRequest 159 { 160 DomainName = domain, 161 RRKeyWord = rr 162 }; 163 var rss = Client.GetAcsResponse(reqq); 164 foreach (var record in rss.DomainRecords) 165 { 166 if (record.DomainName.Equals(domain) && record.RR.Equals(rr)) 167 { 168 return record.RecordId; 169 } 170 } 171 return ""; 172 } 173 #endregion 174 175 #region 獲取公網(wǎng)IP 176 /// <summary> 177 /// 獲取當(dāng)前電腦的真實(shí)外網(wǎng)IP地址,可以自行修改成穩(wěn)定的 178 /// </summary> 179 /// <returns></returns> 180 private static string GetIp() 181 { 182 var myWebClient = new WebClient { Credentials = CredentialCache.DefaultCredentials }; 183 //獲取或設(shè)置用于向Internet資源的請(qǐng)求進(jìn)行身份驗(yàn)證的網(wǎng)絡(luò)憑據(jù) 184 var pageData = myWebClient.DownloadData(IpServer);//從指定網(wǎng)站下載數(shù)據(jù) 185 var all = Encoding.Default.GetString(pageData); //如果獲取網(wǎng)站頁(yè)面采用的是GB2312,則使用這句 186 var regex = @"((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))"; 187 var m = Regex.Match(all, regex); 188 if (m.Success) 189 { 190 return m.Value; 191 } 192 return ""; 193 } 194 #endregion 195 196 #region 獲取配置文件 197 private static Configuration _config; 198 private static Configuration ReadAppConfig() 199 { 200 if (_config == null) 201 { 202 string configPath = AppDomain.CurrentDomain.BaseDirectory+@"/app.config"; 203 _config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() 204 { 205 ExeConfigFilename = configPath 206 }, ConfigurationUserLevel.None); 207 } 208 //MessageBox.Show(config.AppSettings.Settings["serverIp"].Value); 209 return _config; 210 } 211 #endregion 212 } 213 } 為了方便修改參數(shù),特意將所有用到的參數(shù)放到了app.config中,該文件內(nèi)容如下: <?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> </startup> <appSettings> <!--作者:楊浩瑞,yxxrui@163.com,博客:http://www.yxxrui.cn --> <!-- ############################################## --> <!--regionId 區(qū)域--> <!--accessKeyId 阿里云accessKeyId--> <!--accessKeySecret 阿里云accessKeySecret--> <!--recordId 記錄ID,需注意,如果您修改了其他配置,不確定recordId是什么,那么一定要置為空值,系統(tǒng)會(huì)自動(dòng)獲取的--> <!--domain 您的域名,比如:yxxrui.cn--> <!--rr 您的子域名,比如:blog--> <!--TTL 域名的TTL值(生存時(shí)間),默認(rèn)600,請(qǐng)按照阿里云說(shuō)明填寫,若不懂,請(qǐng)不要修改--> <!--lastIP 您的服務(wù)器上次的IP地址,用來(lái)緩存,您無(wú)需修改--> <!--IpServer 獲取IP的服務(wù)器地址,如果自己搭建了獲取公網(wǎng)IP的服務(wù)器,可以換成自己的地址--> <!--WaitTime 重復(fù)執(zhí)行解析域名的間隔時(shí)間,以秒為單位,默認(rèn)60秒--> <add key="regionId" value="cn-hangzhou"/> <add key="accessKeyId" value="123456789"/> <add key="accessKeySecret" value="123456789987654321"/> <add key="recordId" value=""/> <add key="domain" value="yxxrui.cn"/> <add key="rr" value="in"/> <add key="TTL" value="10"/> <add key="lastIP" value=""/> <add key="IpServer" value="http://2018.ip138.com/ic.asp"/> <add key="WaitTime" value="5"/> </appSettings> </configuration> 之前的版本中,沒(méi)有做定時(shí)任務(wù),只做了以下的工作,但是近期發(fā)現(xiàn)使用者還是蠻多的,所以本次終極版專門做了定時(shí)任務(wù)功能。 1、安裝window service,然后會(huì)自定啟動(dòng)定時(shí)任務(wù) 2、獲取當(dāng)前電腦真實(shí)公網(wǎng)IP 3、查看當(dāng)前IP是否有變化 4、若無(wú)變化直接退出,若有變化則修改域名解析設(shè)置 5、等待WaitTime秒后,跳回步驟 2 繼續(xù)執(zhí)行。 此處講一下如何安裝window service,我在安裝包裝放了一個(gè)install.bat,盡量右鍵以管理員身份運(yùn)行,同時(shí)注意別被安全軟件攔截了。 該文章在 2019/9/5 23:05:53 編輯過(guò)
|
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |