【亚洲必赢官网】Net的DNS解析模块,爬虫学习笔记

     
近日在做爬虫的学业,今日读书的内容是有关DNS解析模块的造作的。使用的库为ALacrosseSoft.Tools.Net,它是三个百般有力的开源DNS控件库,包括.Net
SPF validation, SenderID validation以及DNS Client、DNS
Server接口。使用该接口可轻巧实现DNS客户请求端及服务器解析端。

品类地址:,

Nuget包地址:。

率先引进Nuget包:

 

Install-Package ARSoft.Tools.Net

 

 

上边初阶具体落到实处:

/// <summary>
/// DNS解析
/// </summary>
/// <param name="dnsServer">DNS服务器IP</param>
/// <param name="timeOut">解析超时时间</param>
/// <param name="url">解析网址</param>
/// <param name="isSuccess">是否解析成功</param>
/// <returns>解析到的IP信息</returns>
public static IPAddress DnsResolver(string dnsServer, int timeOut, string url, out bool isSuccess)
{
    //初始化DnsClient,第一个参数为DNS服务器的IP,第二个参数为超时时间
    var dnsClient = new DnsClient(IPAddress.Parse(dnsServer), timeOut);
    //解析域名。将域名请求发送至DNS服务器解析,第一个参数为需要解析的域名,第二个参数为
    //解析类型, RecordType.A为IPV4类型
    //DnsMessage dnsMessage = dnsClient.Resolve("www.sina.com", RecordType.A);
    var s = new Stopwatch();
    s.Start();
    var dnsMessage = dnsClient.Resolve(DomainName.Parse(url));
    s.Stop();
    Console.WriteLine(s.Elapsed.Milliseconds);
    //若返回结果为空,或者存在错误,则该请求失败。
    if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
    {
        isSuccess= false;
    }
    //循环遍历返回结果,将返回的IPV4记录添加到结果集List中。
    if (dnsMessage != null)
        foreach (var dnsRecord in dnsMessage.AnswerRecords)
        {
            var aRecord = dnsRecord as ARecord;
            if (aRecord == null) continue;
            isSuccess = true;
            return aRecord.Address;
        }
    isSuccess= false;
    return null;
}

调用方法:

bool isSuccess;
IPAddress ip = DnsResolver("223.5.5.5", 200, "shaoweicloud.cn", out isSuccess);
if (isSuccess)
    Console.WriteLine(ip);

 

     
方今在做爬虫的课业,今日求学的始末是关于DNS解析模块的炮制的。使用的库为ATiggoSoft.Tools.Net,它是二个老大强劲的开源DNS控件库,包涵.Net
SPF validation, SenderID validation以及DNS Client、DNS
Server接口。使用该接口可轻巧实现DNS客户请求端及服务器解析端。

连串地址:,

Nuget包地址:。

率先引进Nuget包:

 

Install-Package ARSoft.Tools.Net

 

 

上面早先具体贯彻:

/// <summary>
/// DNS解析
/// </summary>
/// <param name="dnsServer">DNS服务器IP</param>
/// <param name="timeOut">解析超时时间</param>
/// <param name="url">解析网址</param>
/// <param name="isSuccess">是否解析成功</param>
/// <returns>解析到的IP信息</returns>
public static IPAddress DnsResolver(string dnsServer, int timeOut, string url, out bool isSuccess)
{
    //初始化DnsClient,第一个参数为DNS服务器的IP,第二个参数为超时时间
    var dnsClient = new DnsClient(IPAddress.Parse(dnsServer), timeOut);
    //解析域名。将域名请求发送至DNS服务器解析,第一个参数为需要解析的域名,第二个参数为
    //解析类型, RecordType.A为IPV4类型
    //DnsMessage dnsMessage = dnsClient.Resolve("www.sina.com", RecordType.A);
    var s = new Stopwatch();
    s.Start();
    var dnsMessage = dnsClient.Resolve(DomainName.Parse(url));
    s.Stop();
    Console.WriteLine(s.Elapsed.Milliseconds);
    //若返回结果为空,或者存在错误,则该请求失败。
    if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
    {
        isSuccess= false;
    }
    //循环遍历返回结果,将返回的IPV4记录添加到结果集List中。
    if (dnsMessage != null)
        foreach (var dnsRecord in dnsMessage.AnswerRecords)
        {
            var aRecord = dnsRecord as ARecord;
            if (aRecord == null) continue;
            isSuccess = true;
            return aRecord.Address;
        }
    isSuccess= false;
    return null;
}

调用方法:

bool isSuccess;
IPAddress ip = DnsResolver("223.5.5.5", 200, "shaoweicloud.cn", out isSuccess);
if (isSuccess)
    Console.WriteLine(ip);

 

     
之前大家早就依照ARSoft.Tools.Net简易完成了DNS解析模块的职能,可是当品质需求进步时,每2回爬取都要开始展览DNS请求,甚至很有极大或许1段时间内每一次请求的都是同样的地方,频仍的DNS请求就会变成性能瓶颈,所以大家要通过缓存机制将DNS解析结果缓存下来,下跌DNS解析操作,升高系统性格。

如此这般,大家依据从前封装的MemoryCacheHelper类对DnsResolver类进行改动:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;
using Mem = Crawler.Common.MemoryCacheHelper;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public ARecord Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public TimeSpan TimeToLive { get; set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 10000)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
IsSuccess = false;
if (Mem.Contains(url))
Fill(Mem.Get(url));
else
Dig();
}

private void Fill(DnsResolver resolver)
{
TimeSpan = resolver.TimeSpan;
Url = resolver.Url;
Record = resolver.Record;
DnsServer = resolver.DnsServer;
TimeOut = resolver.TimeOut;
ReturnCode = resolver.ReturnCode;
IsSuccess = resolver.IsSuccess;
}

public void Dig()
{
//开首化DnsClient,第多少个参数为DNS服务器的IP,第叁个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), TimeOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为急需分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若重回结果为空,或然存在错误,则该请求退步。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历重返结果,将赶回的IPV四记下加多到结果集List中。
if (dnsMessage != null)
{
if (dnsMessage.AnswerRecords.Count > 0)
{
Record = dnsMessage.AnswerRecords[0] as ARecord;
if (Record != null)
{
IsSuccess = true;
TimeToLive=new TimeSpan(0,0,Record.TimeToLive);
Mem.Add(Url, this, TimeToLive);
}
}
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

这么,每一回做完DNS解析后,会依据域名的TTL将分析结果缓存下来,下次询问时能够一贯调用缓存,升高系统性子。

0.什么是Redis

Redis是三个开源的施用ANSI
C语言编写、帮助网络、可遵照内部存款和储蓄器亦可持久化的日志型、Key-Value数据库,并提供三种语言的API

—维基百科

一.与别的用户状态保存方案比较

style=”color: #000000;”>1般开荒中用户境况使用session恐怕cookie,二种方法各个利弊。

亚洲必赢官网, style=”color: #000000;”>Session:在InProc方式下轻松丢失,并且引起并发难题。要是采用SQLServer可能SQLServer形式又开支了质量

style=”color: #000000;”>Cookie则轻易将有个别用户音讯揭穿,加解密一样也消耗了质量。

Redis选拔那样的方案化解了多少个难题,

壹.Redis存取进程快。

【亚洲必赢官网】Net的DNS解析模块,爬虫学习笔记。二.用户数据不便于遗失。

三.用户多的情景下轻巧支持集群。

四.力所能及查阅在线用户。

五.能够完成用户一处登陆。(通过代码达成,后续介绍)

陆.支撑持久化。(当然恐怕没什么用)

贰.贯彻思路

style=”color: #000000;”>一.我们知道session其实是在cookie中保存了3个sessionid,用户每一次访问都将sessionid发给服务器,服务器通过ID查找用户对应的动静数据。

style=”color: #000000;”>在那边作者的处理形式也是在cookie中定义3个sessionid,次第需求获取用户景况时将sessionid做为key在Redis中检索。

style=”color: #000000;”>2.同时session协助用户在确按期间不访问将session回收。

style=”color: #000000;”>借用Redis中Keys支持过期日子的性格扶助那一个职能,然而在续期方面需求程序自行拦截请求调用那几个主意(demo有例子)

上边开头代码表明

叁.Redis调用接口

率先引述瑟维斯Stack相关DLL。

style=”color: #000000;”>在web.config增添布局,那些布局用来设置Redis调用地址每台服务用【,】隔绝。主机写在第一位

 

    1 <appSettings>
    2 
    3     <!--每台Redis之间用,分割.第一个必须为主机-->
    4     <add key="SessionRedis" value="127.0.0.1:6384,127.0.0.1:6384"/>
    5 
    6 </appSettings>

早先化配置

static Managers()
{
string sessionRedis= ConfigurationManager.AppSettings[“SessionRedis”];
string timeOut = ConfigurationManager.AppSettings[“SessionRedisTimeOut”];

if (string.IsNullOrEmpty(sessionRedis))
{
throw new Exception(“web.config 贫乏配置SessionRedis,每台Redis之间用,分割.第三个必须为主机”);
}

if (string.IsNullOrEmpty(timeOut)==false)
{
TimeOut = Convert.ToInt32(timeOut);
}

var host = sessionRedis.Split(char.Parse(“,”));
var writeHost = new string[] { host[0] };
var readHosts = host.Skip(1).ToArray();

ClientManagers = new PooledRedisClientManager(writeHost, readHosts, new RedisClientManagerConfig
{
马克斯WritePoolSize = writeReadCount,//“写”链接池链接数
马克斯ReadPoolSize = writeReadCount,//“读”链接池链接数
AutoStart = true
});
}

为了垄断(monopoly)有益写了2个委托

///

/// 写入
///

///
/// ///
public F TryRedisWrite(Func doWrite)
{
PooledRedisClientManager prcm = new Managers().GetClientManagers();
IRedisClient client = null;
try
{
using (client = prcm.GetClient())
{
return doWrite(client);
}
}
catch (RedisException)
{
throw new Exception(“Redis写入十分.Host:” + client.Host + “,Port:” + client.Port);
}
finally
{
if (client != null)
{
client.Dispose();
}
}
}

一个调用的例证其余的现实性看源码

///

/// 以Key/Value的形式存储对象到缓存中
///

/// 对象类别
/// 要写入的集合 public void KSet(Dictionary value)
{
Func fun = (IRedisClient client) =>
{
client.SetAll(value);
return true;
};

TryRedisWrite(fun);
}

4.实现Session

按上面说的给cookie写3个sessionid

///

/// 用户状态管理
///

public class Session
{
///

/// 初始化
///

/// public Session(HttpContextBase _context)
{
var context = _context;
var cookie = context.Request.Cookies.Get(SessionName);
if (cookie == null || string.IsNullOrEmpty(cookie.Value))
{
SessionId = NewGuid();
context.Response.Cookies.Add(new HttpCookie(SessionName, SessionId));
context.Request.Cookies.Add(new HttpCookie(SessionName, SessionId));
}
else
{
SessionId = cookie.Value;
}
}

}

去存取用户的点子

///

/// 获取当前用户信息
///

///
///
public object Get() where T:class,new()
{
return new RedisClient().KGet(SessionId);
}

///

/// 用户是否在线
///

///
public bool IsLogin()
{
return new RedisClient().KIsExist(SessionId);
}

///

/// 登录
///

///
/// public void Login(T obj) where T : class,new()
{
new RedisClient().KSet(SessionId, obj, new TimeSpan(0, Managers.TimeOut, 0));
}

6.续期

暗中认可用户没访问超越三十多分钟注销用户的报到情状,所以用户每一趟访问都要将用户的撤销时间推迟二十八分钟

这要求调用Redis的续期方法

///

/// 延期
///

/// /// public void KSetEntryIn(string key, TimeSpan expiresTime)
{
Func fun = (IRedisClient client) =>
{
client.ExpireEntryIn(key, expiresTime);
return false;
};

TryRedisWrite(fun);
}

封装现在

///

/// 续期
///

public void Postpone()
{
new RedisClient().KSetEntryIn(SessionId, new TimeSpan(0, Managers.TimeOut, 0));
}

那里笔者使用了MVC3中的ActionFilter,拦截用户的装有请求

namespace Test
{
public class SessionFilterAttribute : ActionFilterAttribute
{
///

/// 每次请求都续期
///

/// public override void OnActionExecuting(ActionExecutingContext filterContext)
{
new Session(filterContext.HttpContext).Postpone();
}
}
}

在Global.asax中要注册一下

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new SessionFilterAttribute());
}

protected void Application_Start()
{
RegisterGlobalFilters(GlobalFilters.Filters);
}

5.调用艺术

为了便于调用借用四.0中的新天性,把Controller增添三个扩充属性

public static class ExtSessions
{public static Session SessionExt(this Controller controller)
{
return new Session(controller.HttpContext);
}
}

调用方法

public class HomeController : Controller
{
public ActionResult Index()
{
this.SessionExt().IsLogin();
return View();
}
}

陆.代码下载

点击下载

7.后续

SessionManager包罗 获取用户列表数量,注销有个别用户,根据用户ID获取用户音信,在线用户对象列表,在线用户SessionId列表等办法

 

 

 

 

 

懂的使用格局后我们得以对它做尤其封装,得到DnsResolver类:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public List Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 200)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
Record=new List();
Dig();
}

public void Dig()
{
//初步化DnsClient,第3个参数为DNS服务器的IP,第一个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), TimeOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为索要分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若重回结果为空,或然存在错误,则该请求退步。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历重临结果,将赶回的IPV四记下增多到结果集List中。
if (dnsMessage != null)
foreach (var dnsRecord in dnsMessage.AnswerRecords)
{
var aRecord = dnsRecord as ARecord;
if (aRecord == null) continue;
IsSuccess = true;
Record.Add(aRecord);
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

调用方法:

DnsResolver dns = new DnsResolver("shaoweicloud.cn");
if (dns.IsSuccess)
    Console.WriteLine(dns.Record[0]);

 

        
至此,DNS解析模块就基本告竣了,至于何以标题中标注了半成品,是因为本人想在基本的DNS解析作用的根基上依照分析到DNS音讯中的TTL做1套消息缓存机制,裁减不要求的再度查询,方今还在思量选用何种方法,后续完成会更新。

懂的选择办法后大家能够对它做进一步封装,得到DnsResolver类:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;

namespace Crawler.Protocol
{
public class DnsResolver
{
public TimeSpan TimeSpan { get; set; }
public string Url { get; set; }
public List Record { get; set; }
public string DnsServer { get; set; }
public int TimeOut { get; set; }
public ReturnCode ReturnCode { get; set; }
public bool IsSuccess { get; private set; }
public DnsResolver(string url, string dnsServer = “223.5.5.5”, int timeOut = 200)
{
Url = url;
DnsServer = dnsServer;
TimeOut = timeOut;
Record=new List();
Dig();
}

public void Dig()
{
//开始化DnsClient,第一个参数为DNS服务器的IP,首个参数为超时时间
var dnsClient = new DnsClient(IPAddress.Parse(DnsServer), TimeOut);
var s = new Stopwatch();
s.Start();
//解析域名。将域名请求发送至DNS服务器解析,参数为急需分析的域名
var dnsMessage = dnsClient.Resolve(DomainName.Parse(Url));
s.Stop();
TimeSpan = s.Elapsed;
//若再次回到结果为空,可能存在不当,则该请求失利。
if (dnsMessage == null || (dnsMessage.ReturnCode != ReturnCode.NoError && dnsMessage.ReturnCode != ReturnCode.NxDomain))
IsSuccess = false;
//循环遍历再次来到结果,将重回的IPV四笔录增添到结果集List中。
if (dnsMessage != null)
foreach (var dnsRecord in dnsMessage.AnswerRecords)
{
var aRecord = dnsRecord as ARecord;
if (aRecord == null) continue;
IsSuccess = true;
Record.Add(aRecord);
}
if (dnsMessage != null) ReturnCode = dnsMessage.ReturnCode;
}
}
}

调用方法:

DnsResolver dns = new DnsResolver("shaoweicloud.cn");
if (dns.IsSuccess)
    Console.WriteLine(dns.Record[0]);

 

        
至此,DNS解析模块将要旨竣事了,至于缘何标题中标注了半成品,是因为自个儿想在中央的DNS解析功效的底蕴上依照分析到DNS音讯中的TTL做1套音信缓存机制,收缩不供给的重新查询,近来还在思量选用何种方式,后续达成会更新。