近来在做爬虫的作业,前几日求学的剧情是关于DNS解析模块的炮制的。使用的库为A奇骏Soft.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解析模块的炮制的。使用的库为A奥德赛Soft.Tools.Net,它是五个11分有力的开源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解析模块的功效,然而当质量需要提升时,每一趟爬取都要拓展DNS请求,甚至很有希望壹段时间内每一趟请求的都以同样的地址,频仍的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,第1个参数为超时时间
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是2个开源的利用ANSI
C语言编写、协理网络、可根据内存亦可持久化的日志型、Key-Value数据库,并提供四种语言的API

—维基百科

1.与其余用户状态保存方案比较

Net的DNS解析模块,爬虫学习笔记。 style=”color: #000000;”>一般开荒中用户景况使用session或然cookie,两种方法各个利弊。

style=”color: #000000;”>Session:在InProc形式下轻便丢失,并且引起并发难点。要是利用SQLServer或者SQLServer方式又成本了品质

style=”color: #000000;”>Cookie则轻松将壹部分用户音信暴露,加解密同样也消耗了质量。

Redis采纳那样的方案化解了几个难题,

1.Redis存取进度快。

二.用户数据不易于遗失。

三.用户多的状态下轻易接济集群。

四.可见查阅在线用户。

5.可见落到实处用户壹处登入。(通过代码实现,后续介绍)

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

二.兑现思路

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

style=”color: #000000;”>在此间自身的处理情势也是在cookie中定义二个sessionid,次第须要获得用户情形时将sessionid做为key在Redis中检索。

style=”color: #000000;”>二.同时session支持用户在自然时间不访问将session回收。

style=”color: #000000;”>借用Redis中Keys帮忙过期时间的特征帮助那么些功效,然而在续期方面须要程序活动拦截请求调用这几个格局(demo有例子)

下边初步代码表明

三.Redis调用接口

首先引述ServiceStack相关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之间用,分割.第3个必须为主机”);
}

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
});
}

为了调节有益写了3个委托

///

/// 写入
///

///
/// ///
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写一个sessionid

///

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

public class Session
{
///

/// 初始化
///

/// 金沙注册送58,
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.续期

暗中同意用户没访问超越27分钟注销用户的报到状态,所以用户每趟访问都要将用户的吊销时间推移30分钟

那需求调用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));
}

那里作者动用了MVC叁中的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,第二个参数为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), 提姆eOut);
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做一套新闻缓存机制,缩短不要求的再次查询,目前还在考虑采取何种措施,后续完成会更新。

CopyRight © 2010-2019 金沙注册送58 https://www.3gwork.net/ All Rights Reserved.