前言:稍微介绍下这个代码的用途,在做某些功能的时候,我们可能会用到IP代理,购买IP的时候也是可以选择长期高质量IP或者短失效但量大的IP,这个主要根据用途来购买;这里就是基于大量短失效IP做的一个IP调度,尽可能保证IP能够物尽其用。.
-
首先定义一个
IPPool类,然后在构造函数中传入以下参数public class IPPool{readonly string _ipUrl, _checkUrl;readonly int _saveCount;readonly bool _loopUse;public ConcurrentQueue<string> IPQueue = new ConcurrentQueue<string>();/// <summary>/// 代理IP池/// </summary>/// <param name="ipUrl">代理IP的获取网址</param>/// <param name="checkUrl">检查IP可用性的网址</param>/// <param name="saveCount">IP池的存储量</param>/// <param name="loopUse">是否循环使用</param>public IPPool(string ipUrl, string checkUrl, int saveCount, bool loopUse=true){_ipUrl = ipUrl;_checkUrl = checkUrl;_saveCount = saveCount;_loopUse = loopUse;} -
解析网页上的IP地址,这里使用虚方法,以方便可以重写解析方法,应对不同的数据类型
/// <summary>/// 解析网址IP/// </summary>/// <returns></returns>protected virtual List<string> Parse(){List<string> list = new List<string>();try{HttpClient httpClient = new HttpClient();httpClient.Timeout = new TimeSpan(0, 0, 10);var result = httpClient.GetStringAsync(_ipUrl).Result;JObject jobj = JObject.Parse(result);if (jobj["code"].ToString() == "1"){JArray jarr = (JArray)jobj["data"];foreach (var item in jarr){string ip = item["ip"].ToString() + ":" + item["port"].ToString();list.Add(ip);}}}catch { }return list;} -
检查IP可用性,这里可以使用你需要访问的网址或者百度进行Get,保证可以访问到即可,同样使用虚方法定义
/// <summary>/// 检查IP可用性/// </summary>/// <param name="ip"></param>/// <returns></returns>protected virtual bool Check(string ip){HttpClient httpClient = new HttpClient();httpClient.Timeout = new TimeSpan(0, 0, 10);bool result = httpClient.GetAsync(_checkUrl).Result.StatusCode == HttpStatusCode.OK;return result;} -
开始获取,使用定时器获取,同样因为有设置队列的最大值,所以只有当低于这个阈值时才会进行补充,防止IP浪费的同时保证IP充足够用
/// <summary>/// 开始获取/// </summary>/// <param name="interval">获取间隔</param>public virtual void Start(double interval){System.Timers.Timer timer = new System.Timers.Timer(interval);timer.Elapsed += (s, e) =>{if (IPQueue.Count < _saveCount){List<string> list = Parse();foreach (var ip in list){IPQueue.Enqueue(ip);}}};timer.Start();} -
获取IP,从队列中获取,如果设置了循环使用的话,不失效可以一直使用,进一步保证IP资源
/// <summary>/// 获取IP/// </summary>/// <returns></returns>public virtual string Get(){string ip = null;while (IPQueue.Count > 0){IPQueue.TryPeek(out ip);if (!string.IsNullOrEmpty(ip)&&Check(ip)){if (!_loopUse){IPQueue.TryDequeue(out ip);}break;}else{IPQueue.TryDequeue(out string result);}}return ip;}}
-
为方便测试,我们自定义一个类继承
IPPool,然后重写Parse以及Check方法public IPHelper(string ipUrl, string checkUrl, int saveCount, bool loopUse = true) : base(ipUrl, checkUrl, saveCount,loopUse){}protected override List<string> Parse(){List<string> list = new List<string>();list.Add(DateTime.Now.Ticks.ToString());return list;}protected override bool Check(string ip){return true;} -
最后调用下看看效果
private async void button1_Click(object sender, EventArgs e){listBox1.Items.Clear();IPHelper iPHelper = new IPHelper("", "", 10,false);iPHelper.Start(200);for (int i = 0; i < 5; i++){string ip = iPHelper.Get();if (ip != null){listBox1.Items.Add(ip);}await Task.Delay(500);}}private async void button2_Click(object sender, EventArgs e){listBox1.Items.Clear();IPHelper iPHelper = new IPHelper("", "", 10);iPHelper.Start(200);for (int i = 0; i < 5; i++){string ip = iPHelper.Get();if (ip != null){listBox1.Items.Add(ip);}await Task.Delay(500);}}
实现效果:
