HttpRuntime的认知与抓好明白,异步HTTP乞请操作
分类:计算机编程

一、说明

上边最早介绍HttpRuntime的Web.config里的构造

  1卡塔尔(英语:State of Qatar) 那些类 是本身 在安分守己项目中,优化驱除实际难题时,不参照第三方代码,完全由自身查阅MSDN官方文档 , 实现的叁个实打实坐蓐意况中动用的功力类

<httpRuntime
   executionTimeout = "number" 
   maxRequestLength = "number" 
   requestLengthDiskThreshold = "number" 
   useFullyQualifiedRedirectUrl = "[True|False]" 
   minFreeThreads = "number" 
   minLocalRequestFreeThreads = "number" 
   appRequestQueueLimit = "number"
   enableKernelOutputCache = "[True|False]" 
   enableVersionHeader = "[True|False]" 
   apartmentThreading = "[True|False]"
   requireRootedSaveAsPath = "[True|False]"
   enable = "[True|False]" 
   sendCacheControlHeader = "[True|False]" 
   shutdownTimeout = "number"
   delayNotificationTimeout = "number"
   waitChangeNotification = "number" 
   maxWaitChangeNotification = "number" 
   enableHeaderChecking = "[True|False]" 
/>

  2卡塔尔 读者在选拔此类时,请爱护原创,在代码中拉长原创注释://  Author -- Meng.NET (cnblogs.com卡塔尔(英语:State of Qatar)  ,同一时候应接 三遍纠正、二回创作 以同盟提升

经过上边的安排表达, 上边是在Web.Config里节点的安装

  3卡塔尔国此代码以【面向对象】、【C#闭包】、【异步回调】、【超时】、【等待】、【自动重试】方式贯彻及实现,且能够布署增添

<configuration>
  <system.web>
  <httpRuntime maxRequestLength="4000"
    enable = "True"
    requestLengthDiskThreshold="512
    useFullyQualifiedRedirectUrl="True"
    executionTimeout="45"
    versionHeader="1.1.4128"/>
  </system.web>
</configuration>

二、代码

IIS 所收到的对某 Microsoft ASP.NET 页面包车型大巴各类伏乞都被移交给 ASP.NET HTTP 管线。HTTP 管线由意气风发密密层层托管对象组成,这么些目的按梯次管理该诉求,并成功从 ULX570L 到平凡 HTML 文本的转变。HTTP 管线的入口点是 HttpRuntime 类。ASP.NET 底蕴构造为帮忙进程中所承载的各类 AppDomain 创造此类的三个实例请小心,该支持进度为当前正在运作的每一种 ASP.NET 应用程序维护二个不少年老成的 AppDomain。

  废话非常的少说,上干货,代码如下:

要激活 HTTP 管道,能够成立二个 HttpRuntime 类的新实例,然后调用其 ProcessRequest 方法。叁个完完全全的页面要求会席卷上边包车型大巴流程:
先是被WWW服务器截获(inetinfo.exe进度), 该进度首先判定页面后缀, 然后基于IIS中结构决定调用具体的扩充程序。aspx就能够调用aspnet_isapi.dll,
然后由aspnet_isapi.dll发送给w3wp.exe(iis 工小编经过,IIS6.0中称之为 w3wq.exe,IIS5.0中称之为 aspnet_wp.exe)。

图片 1图片 2

接下去在w3wp.exe调用.NET类库举办实际管理,顺序如下:ISAPIRuntim, HttpRuntime, HttpApplicationFactory, HttpApplication, HttpModule, HttpHandlerFactory, HttpHandler

  1     /// <summary>
  2     /// 异步 Http
  3     /// </summary>
  4     public class Remoter
  5     {
  6         /*
  7          * LM,2016/08/18
  8          * C#闭包化,异步化,Web操作
  9          * 以便支持POS多接口多操作同时使用
 10          */
 11 
 12         /// <summary>
 13         /// 请求地址
 14         /// </summary>
 15         public string URL { get; set; }
 16 
 17         /// <summary>
 18         /// 请求方式
 19         /// </summary>
 20         public string RequestMethod { get; set; }
 21 
 22         /// <summary>
 23         /// 请求数据
 24         /// </summary>
 25         public string JsonContent { get; set; }
 26 
 27         //
 28         private byte[] Buffer { get; set; }        
 29         private Stream RequestStream { get; set; }        
 30         private HttpWebRequest Request { get; set; }        
 31         private bool ResponseFlag { get; set; }        
 32         private string Result { get; set; }        
 33         private bool TimeoutFlag  { get; set; }        
 34         private int TimeoutTime { get; set; }        
 35         private bool RetryFlag { get; set; }        
 36         private int RetryCount  { get; set; }        
 37         private int WaitSleep { get; set; }        
 38         private int TrySleep { get; set; }
 39 
 40         // 初始化
 41         public Remoter()
 42         {
 43             //
 44             ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
 45             ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback((object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) => true);
 46 
 47             // 
 48             this.URL = string.Empty;
 49             this.Request = default(HttpWebRequest);
 50             this.JsonContent = string.Empty;
 51             this.Buffer = default(byte[]);
 52             this.RequestStream = default(Stream);
 53             this.ResponseFlag = false;
 54             this.Result = string.Empty;
 55             this.TimeoutFlag = false;
 56             this.TimeoutTime = 10 * 1000;
 57             this.RetryFlag = false;
 58             this.RetryCount = 3;
 59             this.WaitSleep = 10;
 60             this.RequestMethod = "POST";
 61             this.TrySleep = 2000;
 62         }
 63         
 64         /// <summary>
 65         /// 获取响应数据
 66         /// </summary>
 67         public string GetRemoteData()
 68         {
 69             //
 70             if(string.IsNullOrWhiteSpace(this.URL))
 71             {
 72                 throw new Exception("HttpAsync.URL,未赋值!");
 73             }
 74 
 75             // 
 76             RemoteNew(SetResult); 
 77 
 78             //
 79             var timeNum = 0;
 80             while (true)
 81             {
 82                 if (ResponseFlag)
 83                 {
 84                     break;
 85                 }
 86                 if (TimeoutFlag)
 87                 {
 88                     throw new Exception(string.Format("请求超时!超时时间:{0}S", TimeoutTime / 1000));
 89                 }
 90                 timeNum  = WaitSleep;
 91                 if (timeNum >= TimeoutTime)
 92                 {
 93                     TimeoutFlag = true;
 94                 }
 95                 Thread.Sleep(WaitSleep);
 96             }
 97 
 98             //
 99             return Result;
100         }
101 
102         // 
103         private void RemoteNew(Action<Remoter, string> action) 
104         {
105             //
106             var reNum = 0;
107             for (var i = 0; i < this.RetryCount; i  )
108             {
109                 try
110                 {
111                     //
112                     var uri = URL;
113 
114                     //
115                     this.Request = WebRequest.Create(uri) as HttpWebRequest;
116                     this.Request.KeepAlive = false;
117                     this.Request.Method = this.RequestMethod;
118                     this.Request.Credentials = CredentialCache.DefaultCredentials;
119                     if (this.RequestMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
120                     {
121                         this.Buffer = Encoding.UTF8.GetBytes(this.JsonContent);
122                         this.Request.ContentLength = this.Buffer.Length;
123                         this.Request.ContentType = "application/json";
124                         this.RequestStream = this.Request.GetRequestStream();
125                         this.RequestStream.Write(this.Buffer, 0, this.Buffer.Length);
126                         this.RequestStream.Close();
127                     }
128 
129                     //
130                     this.Request.BeginGetResponse((arr) =>
131                     {
132                         //
133                         var state = arr.AsyncState as Remoter;
134                         //
135                         var response = state.Request.EndGetResponse(arr) as HttpWebResponse;
136                         var respStream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("UTF-8"));
137                         action(state, respStream.ReadToEnd());
138                         respStream.Close();
139                         response.Close();
140                     }, this);
141                     //
142                     break;
143                 }
144                 catch (Exception ex)
145                 {
146                     Thread.Sleep(this.TrySleep);
147                     reNum  ;
148                     if (reNum == this.RetryCount)
149                     {
150                         throw new Exception(string.Format("重试失败!重试次数:{0}次,失败原因:{1}", this.RetryCount, ex.Message));
151                     }
152                     continue;
153                 }
154             }
155         }        
156         private void SetResult(Remoter state, string jsonData)
157         {
158             if (!string.IsNullOrWhiteSpace(jsonData))
159             {
160                 state.Result = jsonData;
161                 state.ResponseFlag = true;
162             }
163         }
164     }

ISAPIRuntime:重要功效是调用一些非托管代码生成HttpWorkerRequest对象,HttpWorkerRequest对象包含当前恳请的保有音讯,然后传递给HttpRuntime
HttpRuntime:遵照HttpWorkerRequest对象生成HttpContext,HttpContext满含request、response等属性, 再调用HttpApplicationFactory来生成IHttpHandler, 调用HttpApplication对象实践乞求
HttpApplicationFactory: 生成叁个HttpApplication对象
HttpApplication:进行HttpModule的开端化,HttpApplication创设针对此Http乞求的 HttpContext对象
HttpModule: 当二个HTTP乞求达到HttpModule时,整个ASP.NET Framework系统还并从未对这几个HTTP央求做别的管理,也正是说那时候对于HTTP央浼来说,HttpModule是一个HTTP央求的“必供给经过的路”,所以能够在这里个HTTP诉求传递到实在的乞请处理为主(HttpHandler)在此以前附加一些亟待的新闻在此个HTTP央浼消息之上,或然针对截获的这几个HTTP央求消息作一些非常的做事,可能在有个别景况下干脆终止知足一些标准化的HTTP供给,从而得以起到多少个Filter过滤器的意义。
HttpHandlerFactory:把客商request 转载到HttpHandlerFactory,再由HttpHandlerFactory实例化HttpHandler对象来对景挂画request
HttpHandle:Http管理程序,管理页面需要

Remoter.cs

从地点看出HttpRuntime在那之中有一个ProcessRequest 方法
public static void ProcessRequest(HttpWorkerRequest wr卡塔尔国;  //驱动全部ASP.NET Web 管理实践。伪代码如下:

  使用办法:

public static void HttpRuntime.ProcessRequest(HttpWorkerRequest wr)
 {
   // 检查当前调用者有未有作为ASP.NET宿主(Host卡塔尔(قطر‎的权柄
   InternalSecurityPermissions.AspNetHostingPermissionLevelMedium.Demand(); 

  GET: 

   if(wr == null)
   {
     throw new ArgumentNullException("custom");
   }

图片 3图片 4

   RequestQueue queue = HttpRuntime._theRuntime._requestQueue;

1 var remoter = new Remoter();
2 remoter.RequestMethod = "GET";
3 remoter.URL = "这里是你要请求的URL";
4 var response = remoter.GetRemoteData();

   if(queue != null)
   {
     // 将参数中的Web页面伏乞归入需要队列中, 并从队列中使用FIFO战术获取八个页面伏乞
     wr = queue.GetRequestToExecute(wr);
   }

View Code

   if(wr != null)
   {     
     HttpRuntime.CalculateWaitTimeAndUpdatePerfCounter(wr卡塔尔国; // 更新性能计数器     
      HttpRuntime.ProcessRequestNow(wr卡塔尔(英语:State of Qatar); // 实际达成页面伏乞工作
   }
 }

  POST:

ProcessRequestNow函数则一向调用缺省HttpRuntime实例的ProcessRequestInternal函数完结实际页面央求职业,伪代码如下:

图片 5图片 6

internal static void HttpRuntime.ProcessRequestNow(HttpWorkerRequest wr)
{
   HttpRuntime._theRuntime.ProcessRequestInternal(wr);
}

1 var remoter = new Remoter();
2 remoter.RequestMethod = "POST";
3 remoter.URL = "你要请求的URL";
4 remoter.JsonContent = "你要想URL发送的JSON数据";
5 var response = remoter.GetRemoteData();

ProcessRequestInternal函数逻辑稍稍复杂一些,大致可分为四个部分:
反省当前HttpRuntime实例是还是不是第一次被调用,假设是首先次调用则通过FirstRequestInit函数伊始化
调用HttpResponse.InitResponseWriter函数开头化页面乞求的归来对象HttpWorkerRequest.Response
调用HttpApplicationFactory.GetApplicationInstance函数获取当前 Web 应用程序实例
动用Web应用程序实例实现实际的页面伏乞职业
伪代码如下:

View Code

图片 7图片 8Code
private void HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
 {
   // 构造 HTTP 调用上下文对象
   HttpContext ctxt = new HttpContext(wr, 0); 

三、代码剖析

   // 设置发送甘休异步回调函数
   wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, ctxt);

    public Remoter(卡塔尔国开头化本类,可配备到 App.config/Web.config 中

   // 更新诉求计数器
   Interlocked.Increment(&(this._activeRequestCount));

图片 9图片 10

   try
   {
     // 检查当前HttpRuntime实例是不是第三遍被调用
     if(this._beforeFirstRequest)
     {
       lock(this)
       {
         // 使用 Double-Checked 方式 防止冗余锁定
         if(this._beforeFirstRequest)
         {
           this._firstRequestStartTime = DateTime.UtcNow;
           this.FirstRequestInit(ctxt卡塔尔; // 开端化当前 HttpRuntime 运营时环境
           this._beforeFirstRequest = false;
         }
       }
     }

 1             // 
 2             this.URL = string.Empty;
 3             this.Request = default(HttpWebRequest);
 4             this.JsonContent = string.Empty;
 5             this.Buffer = default(byte[]);
 6             this.RequestStream = default(Stream);
 7             this.ResponseFlag = false;
 8             this.Result = string.Empty;
 9             this.TimeoutFlag = false;
10             this.TimeoutTime = 10 * 1000;
11             this.RetryFlag = false;
12             this.RetryCount = 3;
13             this.WaitSleep = 10;
14             this.RequestMethod = "POST";
15             this.TrySleep = 2000;

     // 依照安排文件设置,扮演具有较Gott权的剧中人物
     ctxt.Impersonation.Start(true, false);
     try
     {
       // 初步化页面央求的回来对象
       ctxt.Response.InitResponseWriter();
     }
     finally
     {
       ctxt.Impersonation.Stop();
     }

可从布置文件读取部分

     // 获取当前 Web 应用程序实例
     IHttpHandler handler = HttpApplicationFactory.GetApplicationInstance(ctxt);

  public string U昂科拉L 要倡议的地方

     if (handler == null)
     {
       throw new HttpException(HttpRuntime.FormatResourceString("Unable_create_app_object"));
     }

  public string RequestMethod HTTP 动词

     // 使用Web应用程序实例达成实际的页面央浼工作
     if((handler as IHttpAsyncHandler) != null)
     {
       IHttpAsyncHandler asyncHandler = ((IHttpAsyncHandler) handler);
       ctxt.AsyncAppHandler = asyncHandler;
       // 使用异步管理体制
       asyncHandler.BeginProcessRequest(ctxt, this._handlerCompletionCallback, ctxt);
     }
     else
     {
       handler.ProcessRequest(ctxt);
       this.FinishRequest(ctxt.WorkerRequest, ctxt, null);
     }
   }
   catch(Exception E)
   {
     ctxt.Response.InitResponseWriter();
     this.FinishRequest(wr, ctxt, E);
   }
 }

  public string JsonContent POST 请求时,发送的json数据

HttpRuntime.ProcessRequestInternal函数中调用了HttpApplicationFactory.GetApplicationInstance函数获取当前 Web 应用程序实例。起码HttpRuntime已经完完结,将转进HttpApplicationFactory阶段流程。我们可以看出,围绕HttpRuntime的函数皆有贰个HttpWorkerRequest参数,下边简要介绍一下那么些参数的效果与利益。在ISAPIRuntime阶段,调用一些非托管代码生成HttpWorkerRequest对象,该对象包罗当前倡议的具备消息,然后传递给HttpRuntime,这里生成的HttpWorkerRequest对象可以直接在我们的页面里调用.
IServiceProvider provider=(IServiceProvider)HttpContext.Current;
HttpWorkerRequest wr=(HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
接下来能够透过wr来调用里面包车型地铁法子。关于HttpWorkerRequest类里面包蕴的办法,从其元数据之中能够看见,如下:

  private byte[] Buffer 设置哀告流的byte数组

图片 11图片 12Code
public abstract class HttpWorkerRequest
    {
        // 摘要:
        //     钦定 AcceptHTTP 标头的索引号。
        public const int HeaderAccept = 20;
        //
        // 摘要:
        //     钦命 Accept-CharsetHTTP 标头的索引号。
        public const int HeaderAcceptCharset = 21;
        //
        // 摘要:
        //     钦赐 Accept-EncodingHTTP 标头的索引号。
        public const int HeaderAcceptEncoding = 22;
        //
        // 摘要:
        //     内定 Accept-LanguageHTTP 标头的索引号。
        public const int HeaderAcceptLanguage = 23;
        //
        // 摘要:
        //     钦定 Accept-RangesHTTP 标头的索引号。
        public const int HeaderAcceptRanges = 20;
        //
        // 摘要:
        //     内定 AgeHTTP 标头的索引号。
        public const int HeaderAge = 21;
        //
        // 摘要:
        //     钦点 AllowHTTP 标头的索引号。
        public const int HeaderAllow = 10;
        //
        // 摘要:
        //     钦命 AuthorizationHTTP 标头的索引号。
        public const int HeaderAuthorization = 24;
        //
        // 摘要:
        //     表示 HTTPCache-ControlHTTP 标头的目录。
        public const int HeaderCacheControl = 0;
        //
        // 摘要:
        //     钦赐 ConnectionHTTP 标头的索引号。
        public const int HeaderConnection = 1;
        //
        // 摘要:
        //     钦点 Content-EncodingHTTP 标头的索引号。
        public const int HeaderContentEncoding = 13;
        //
        // 摘要:
        //     钦命 Content-LanguageHTTP 标头的索引号。
        public const int HeaderContentLanguage = 14;
        //
        // 摘要:
        //     内定 Content-LengthHTTP 标头的索引号。
        public const int HeaderContentLength = 11;
        //
        // 摘要:
        //     钦点 Content-LocationHTTP 标头的索引号。
        public const int HeaderContentLocation = 15;
        //
        // 摘要:
        //     钦赐 Content-MD5HTTP 标头的索引号。
        public const int HeaderContentMd5 = 16;
        //
        // 摘要:
        //     钦命 Content-RangeHTTP 标头的索引号。
        public const int HeaderContentRange = 17;
        //
        // 摘要:
        //     钦命 Content-TypeHTTP 标头的索引号。
        public const int HeaderContentType = 12;
        //
        // 摘要:
        //     钦点 CookieHTTP 标头的索引号。
        public const int HeaderCookie = 25;
        //
        // 摘要:
        //     钦命 DateHTTP 标头的索引号。
        public const int HeaderDate = 2;
        //
        // 摘要:
        //     钦定 ETagHTTP 标头的索引号。
        public const int HeaderEtag = 22;
        //
        // 摘要:
        //     钦点 ExceptHTTP 标头的索引号。
        public const int HeaderExpect = 26;
        //
        // 摘要:
        //     钦赐 ExpiresHTTP 标头的索引号。
        public const int HeaderExpires = 18;
        //
        // 摘要:
        //     钦点 FromHTTP 标头的索引号。
        public const int HeaderFrom = 27;
        //
        // 摘要:
        //     钦定 HostHTTP 标头的索引号。
        public const int HeaderHost = 28;
        //
        // 摘要:
        //     钦命 If-MatchHTTP 标头的索引号。
        public const int HeaderIfMatch = 29;
        //
        // 摘要:
        //     内定 If-Modified-SinceHTTP 标头的索引号。
        public const int HeaderIfModifiedSince = 30;
        //
        // 摘要:
        //     钦命 If-None-MatchHTTP 标头的索引号。
        public const int HeaderIfNoneMatch = 31;
        //
        // 摘要:
        //     内定 If-RangeHTTP 标头的索引号。
        public const int HeaderIfRange = 32;
        //
        // 摘要:
        //     钦命 If-Unmodified-SinceHTTP 标头的索引号。
        public const int HeaderIfUnmodifiedSince = 33;
        //
        // 摘要:
        //     钦定 Keep-AliveHTTP 标头的索引号。
        public const int HeaderKeepAlive = 3;
        //
        // 摘要:
        //     内定 Last-ModifiedHTTP 标头的索引号。
        public const int HeaderLastModified = 19;
        //
        // 摘要:
        //     内定 LocationHTTP 标头的索引号。
        public const int HeaderLocation = 23;
        //
        // 摘要:
        //     钦命 Max-ForwardsHTTP 标头的索引号。
        public const int HeaderMaxForwards = 34;
        //
        // 摘要:
        //     内定 PragmaHTTP 标头的索引号。
        public const int HeaderPragma = 4;
        //
        // 摘要:
        //     内定 Proxy-AuthenticateHTTP 标头的索引号。
        public const int HeaderProxyAuthenticate = 24;
        //
        // 摘要:
        //     钦赐 Proxy-AuthorizationHTTP 标头的索引号。
        public const int HeaderProxyAuthorization = 35;
        //
        // 摘要:
        //     内定 RangeHTTP 标头的索引号。
        public const int HeaderRange = 37;
        //
        // 摘要:
        //     钦定 RefererHTTP 标头的索引号。
        public const int HeaderReferer = 36;
        //
        // 摘要:
        //     钦命 Retry-AfterHTTP 标头的索引号。
        public const int HeaderRetryAfter = 25;
        //
        // 摘要:
        //     钦点 ServerHTTP 标头的索引号。
        public const int HeaderServer = 26;
        //
        // 摘要:
        //     内定 Set-CookieHTTP 标头的索引号。
        public const int HeaderSetCookie = 27;
        //
        // 摘要:
        //     内定 TEHTTP 标头的索引号。
        public const int HeaderTe = 38;
        //
        // 摘要:
        //     钦定 TrailerHTTP 标头的索引号。
        public const int HeaderTrailer = 5;
        //
        // 摘要:
        //     钦赐 Transfer-EncodingHTTP 标头的索引号。
        public const int HeaderTransferEncoding = 6;
        //
        // 摘要:
        //     内定 UpgradeHTTP 标头的索引号。
        public const int HeaderUpgrade = 7;
        //
        // 摘要:
        //     内定 User-AgentHTTP 标头的索引号。
        public const int HeaderUserAgent = 39;
        //
        // 摘要:
        //     钦定 VaryHTTP 标头的索引号。
        public const int HeaderVary = 28;
        //
        // 摘要:
        //     钦点 ViaHTTP 标头的索引号。
        public const int HeaderVia = 8;
        //
        // 摘要:
        //     内定 WarningHTTP 标头的索引号。
        public const int HeaderWarning = 9;
        //
        // 摘要:
        //     钦点 WWW-AuthenticateHTTP 标头的索引号。
        public const int HeaderWwwAuthenticate = 29;
        //
        // 摘要:
        //     钦点央求的原因。
        public const int ReasonCachePolicy = 2;
        //
        // 摘要:
        //     钦命乞求的自始自终的经过。
        public const int ReasonCacheSecurity = 3;
        //
        // 摘要:
        //     钦点央求的因由。
        public const int ReasonClientDisconnect = 4;
        //
        // 摘要:
        //     钦定供给的来头。暗中同意值为 System.Web.HttpWorkerRequest.ReasonResponseCacheMiss。
        public const int ReasonDefault = 0;
        //
        // 摘要:
        //     钦定伏乞的缘故。
        public const int ReasonFileHandleCacheMiss = 1;
        //
        // 摘要:
        //     钦命央求的原由。
        public const int ReasonResponseCacheMiss = 0;
        //
        // 摘要:
        //     钦定 MaximumHTTP 央求标头的索引号。
        public const int RequestHeaderMaximum = 40;
        //
        // 摘要:
        //     内定 MaximumHTTP 响应标头的索引号。
        public const int ResponseHeaderMaximum = 30;

  private Stream RequestStream 请求流

        // 摘要:
        //     开头化 System.Web.HttpWorkerRequest 类的新实例。
        protected HttpWorkerRequest();

  private HttpWebRequest Request HTTP央求对象

        // 摘要:
        //     获取 Machine.config 文件的完全物理路线。
        //
        // 重回结果:
        //     Machine.config 文件的物理路线。
        public virtual string MachineConfigPath { get; }
        //
        // 摘要:
        //     获取 ASP.NET 二进制文件的装置目录的概况路线。
        //
        // 重临结果:
        //     ASP.NET 二进制文件的大要目录。
        public virtual string MachineInstallDirectory { get; }
        //
        // 摘要:
        //     获取当前呼吁的 Windows 追踪 ID 的照望事件追踪。
        //
        // 再次回到结果:
        //     当前 ASP.NET 须要的追踪 ID。
        public virtual Guid RequestTraceIdentifier { get; }
        //
        // 摘要:
        //     获取根 Web.config 文件的完全物理路线。
        //
        // 重返结果:
        //     根 Web.config 文件的大要路线。
        public virtual string RootWebConfigPath { get; }

  private bool ResponseFlag 与央浼对应的响应是不是成功标志

        // 摘要:
        //     终止与客户端的总是。
        public virtual void CloseConnection();
        //
        // 摘要:
        //     由运行库使用以通告 System.Web.HttpWorkerRequest 当前央浼的央浼管理已到位。
        public abstract void EndOfRequest();
        //
        // 摘要:
        //     将兼具挂起的响应数据发送到客商端。
        //
        // 参数:
        //   finalFlush:
        //     假若那将是最后三次刷新响应数据,则为 true;不然为 false。
        public abstract void FlushResponse(bool finalFlush);
        //
        // 摘要:
        //     再次回到当前正值施行的服务器应用程序的杜撰路线。
        //
        // 重临结果:
        //     当前应用程序的伪造路线。
        public virtual string GetAppPath();
        //
        // 摘要:
        //     再次来到当前正值实行的服务器应用程序的物理路线。
        //
        // 再次来到结果:
        //     当前应用程序的物理路线。
        public virtual string GetAppPathTranslated();
        //
        // 摘要:
        //     在派生类中被重写时,重回当前 U中华VL 的应用程序池 ID。
        //
        // 重回结果:
        //     始终再次回到 null。
        public virtual string GetAppPoolID();
        //
        // 摘要:
        //     获取从客商端读入的字节数。
        //
        // 再次回到结果:
        //     富含读取的字节数的 Long。
        public virtual long GetBytesRead();
        //
        // 摘要:
        //     在派生类中被重写时,从顾客端发出的央浼获取证书字段(以 X.509 标准钦点)。
        //
        // 再次回到结果:
        //     包罗全部证书内容流的字节数组。
        public virtual byte[] GetClientCertificate();
        //
        // 摘要:
        //     获取证书颁发者(以二进制格式表示)。
        //
        // 重回结果:
        //     包罗以二进制格式表示的证件颁发者的字节数组。
        public virtual byte[] GetClientCertificateBinaryIssuer();
        //
        // 摘要:
        //     在派生类中被重写时,重临用于编码客商端证书的 System.Text.Encoding 对象。
        //
        // 再次回到结果:
        //     表示为整数的证书编码。
        public virtual int GetClientCertificateEncoding();
        //
        // 摘要:
        //     在派生类中被重写时,获取与客商端证书关联的 PublicKey 对象。
        //
        // 重临结果:
        //     一个 PublicKey 对象。
        public virtual byte[] GetClientCertificatePublicKey();
        //
        // 摘要:
        //     在派生类中被重写时,则收获证书开首生效的日期。此日期随区域安装的例外而各异。
        //
        // 重返结果:
        //     表示证文人效时间的 System.DateTime 对象。
        public virtual DateTime GetClientCertificateValidFrom();
        //
        // 摘要:
        //     获取证书到期日期。
        //
        // 重返结果:
        //     表示证书失效日期的 System.DateTime 对象。
        public virtual DateTime GetClientCertificateValidUntil();
        //
        // 摘要:
        //     在派生类中被重写时,重回当前连连的 ID。
        //
        // 重回结果:
        //     始终重回 0。
        public virtual long GetConnectionID();
        //
        // 摘要:
        //     在派生类中被重写时,重返所央求的 UTiggoI 的虚构路线。
        //
        // 再次来到结果:
        //     请求的 URI 的路径。
        public virtual string GetFilePath();
        //
        // 摘要:
        //     重返乞求的 U福特ExplorerI 的大意文件路径(并将其从虚构路线调换到物理路线:举例,从“/proj1/page.aspx”调换到“c:dirpage.aspx”)
        //
        // 重临结果:
        //     要求的 URubiconI 的已转移的物理文件路线。
        public virtual string GetFilePathTranslated();
        //
        // 摘要:
        //     重返供给标头的内定成员。
        //
        // 重回结果:
        //     伏乞标头中回到的 HTTP 谓词。
        public abstract string GetHttpVerbName();
        //
        // 摘要:
        //     提供对央浼的 HTTP 版本(如“HTTP/1.1”)的拜候。
        //
        // 重返结果:
        //     要求标头中回到的 HTTP 版本。
        public abstract string GetHttpVersion();
        //
        // 摘要:
        //     再次回到与钦定的索引相对应的规范 HTTP 供给标头。
        //
        // 参数:
        //   index:
        //     标头的目录。比方,System.Web.HttpWorkerRequest.HeaderAllow 字段。
        //
        // 再次回到结果:
        //     HTTP 央浼标头。
        public virtual string GetKnownRequestHeader(int index);
        //
        // 摘要:
        //     再次来到钦点的 HTTP 伏乞标头的索引号。
        //
        // 参数:
        //   header:
        //     标头的名目。
        //
        // 重回结果:
        //     在 header 参数中钦点的 HTTP 央求标头的索引号。
        public static int GetKnownRequestHeaderIndex(string header);
        //
        // 摘要:
        //     再次回到钦点的 HTTP 乞请标头的称谓。
        //
        // 参数:
        //   index:
        //     标头的索引号。
        //
        // 重返结果:
        //     在 index 参数中钦定的 HTTP 乞求标头的名目。
        public static string GetKnownRequestHeaderName(int index);
        //
        // 摘要:
        //     再次来到内定的 HTTP 响应标头的索引号。
        //
        // 参数:
        //   header:
        //     HTTP 标头的名目。
        //
        // 再次来到结果:
        //     在 header 参数中内定的 HTTP 响应标头的索引号。
        public static int GetKnownResponseHeaderIndex(string header);
        //
        // 摘要:
        //     重返钦命的 HTTP 响应标头的称呼。
        //
        // 参数:
        //   index:
        //     标头的索引号。
        //
        // 重临结果:
        //     在 index 参数中钦赐的 HTTP 响应标头的名称。
        public static string GetKnownResponseHeaderName(int index);
        //
        // 摘要:
        //     提供对央浼标头的钦命成员的拜访。
        //
        // 再次来到结果:
        //     央浼标头中回到的服务器 IP 地址。
        public abstract string GetLocalAddress();
        //
        // 摘要:
        //     提供对央浼标头的钦赐成员的拜谒。
        //
        // 再次回到结果:
        //     央求标头中回到的劳动器端口号。
        public abstract int GetLocalPort();
        //
        // 摘要:
        //     重回具备 USportageL 扩充的财富的任何渠道音讯。即对于路线 /virdir/page.html/tail,Get帕特hInfo 值为 /tail。
        //
        // 重回结果:
        //     财富的附加路线新闻。
        public virtual string GetPathInfo();
        //
        // 摘要:
        //     重返 HTTP 供给正文已被读取的有的。
        //
        // 再次来到结果:
        //     HTTP 诉求正文已被读取的一些。
        public virtual byte[] GetPreloadedEntityBody();
        //
        // 摘要:
        //     使用钦命的缓冲区数据和字节偏移量获取 HTTP 恳求正文当前已被读取的片段。
        //
        // 参数:
        //   buffer:
        //     要读取的多寡。
        //
        //   offset:
        //     起头读取的岗位的字节偏移量。
        //
        // 再次回到结果:
        //     HTTP 诉求正文已被读取的部分。
        public virtual int GetPreloadedEntityBody(byte[] buffer, int offset);
        //
        // 摘要:
        //     获取 HTTP 央浼正文当前已被读取部分的长度。
        //
        // 重临结果:
        //     二个子弹头,包蕴当前已读取的 HTTP 诉求正文的长度。
        public virtual int GetPreloadedEntityBodyLength();
        //
        // 摘要:
        //     在派生类中被重写时,重返 HTTP 协议(HTTP 或 HTTPS)。
        //
        // 再次来到结果:
        //     如果 System.Web.HttpWorkerRequest.IsSecure() 方法为 true,则为 HTTPS;否则,为 HTTP。
        public virtual string GetProtocol();
        //
        // 摘要:
        //     再次来到乞求 UEscortL 中内定的查询字符串。
        //
        // 重回结果:
        //     央求查询字符串。
        public abstract string GetQueryString();
        //
        // 摘要:
        //     在派生类中被重写时,以字节数组的款式重临响应查询字符串。
        //
        // 重返结果:
        //     满含响应的字节数组。
        public virtual byte[] GetQueryStringRawBytes();
        //
        // 摘要:
        //     重回附加了查询字符串的央浼标头中包括的 UXC90L 路线。
        //
        // 重返结果:
        //     必要标头的原始 UHavalL 路线。
        public abstract string GetRawUrl();
        //
        // 摘要:
        //     提供对诉求标头的钦点成员的拜见。
        //
        // 再次回到结果:
        //     客商端的 IP 地址。
        public abstract string GetRemoteAddress();
        //
        // 摘要:
        //     在派生类中被重写时,再次回到客商端计算机的称谓。
        //
        // 再次回到结果:
        //     客商端Computer的称呼。
        public virtual string GetRemoteName();
        //
        // 摘要:
        //     提供对央浼标头的钦点成员的走访。
        //
        // 再次来到结果:
        //     客商端的 HTTP 端口号。
        public abstract int GetRemotePort();
        //
        // 摘要:
        //     在派生类中被重写时,再次回到央浼的开始和结果。
        //
        // 重返结果:
        //     原因代码。暗中同意值为 ReasonResponseCacheMiss。
        public virtual int GetRequestReason();
        //
        // 摘要:
        //     在派生类中被重写时,重回本地服务器的名目。
        //
        // 重回结果:
        //     本地服务器的名称。
        public virtual string GetServerName();
        //
        // 摘要:
        //     从与恳求关联的服务器变量词典再次回到单个服务器变量。
        //
        // 参数:
        //   name:
        //     央浼的服务器变量的名目。
        //
        // 重返结果:
        //     诉求的服务器变量。
        public virtual string GetServerVariable(string name);
        //
        // 摘要:
        //     重返二个字符串,该字符串描述钦命的 HTTP 状态代码的称呼。
        //
        // 参数:
        //   code:
        //     HTTP 状态代码。
        //
        // 再次来到结果:
        //     状态表明。比方,System.Web.HttpWorkerRequest.GetStatusDescription(System.Int32卡塔尔(英语:State of Qatar) (404卡塔尔(英语:State of Qatar)
        //     返回“未找到”。
        public static string GetStatusDescription(int code);
        //
        // 摘要:
        //     获取整个 HTTP 乞请正文的长短。
        //
        // 重返结果:
        //     包罗全体 HTTP 请求正文的长短的卡尺头。
        public virtual int GetTotalEntityBodyLength();
        //
        // 摘要:
        //     重返非标准的 HTTP 须求标头值。
        //
        // 参数:
        //   name:
        //     标第一名称。
        //
        // 再次来到结果:
        //     标头值。
        public virtual string GetUnknownRequestHeader(string name);
        //
        // 摘要:
        //     获取具有非规范的 HTTP 标头的名称/值对。
        //
        // 再次来到结果:
        //     标头的称谓/值没错数组。
        [CLSCompliant(false)]
        public virtual string[][] GetUnknownRequestHeaders();
        //
        // 摘要:
        //     重返央浼的 U奥迪Q3I 的虚构路径。
        //
        // 再次回到结果:
        //     请求的 URI 的路径。
        public abstract string GetUriPath();
        //
        // 摘要:
        //     当在派生类中被重写时,重临当前连年的内外文 ID。
        //
        // 再次来到结果:
        //     始终重临 0。
        public virtual long GetUrlContextID();
        //
        // 摘要:
        //     在派生类中被重写时,再次来到客商端的依葫芦画瓢标志。
        //
        // 再次来到结果:
        //     表示客商端的效仿标志的值。暗中同意值为 0。
        public virtual IntPtr GetUserToken();
        //
        // 摘要:
        //     获取恳求虚构路线的模仿标识。
        //
        // 重返结果:
        //     央浼设想路线的标志的非托管内部存款和储蓄器指针。
        public virtual IntPtr GetVirtualPathToken();
        //
        // 摘要:
        //     再次回到一个值,该值提示央浼是还是不是包蕴正文数据。
        //
        // 再次来到结果:
        //     假设央浼富含正文数据,则为 true;不然,为 false。
        public bool HasEntityBody();
        //
        // 摘要:
        //     重临二个值,该值提示是还是不是已为当前的倡议将 HTTP 响应标头发送到客商端。
        //
        // 重临结果:
        //     假使 HTTP 响应标头已发送到顾客端,则为 true;不然,为 false。
        public virtual bool HeadersSent();
        //
        // 摘要:
        //     再次回到二个值,该值提醒顾客端连接是还是不是仍居于活动状态。
        //
        // 重临结果:
        //     尽管客户端连接仍居于活动状态,则为 true;不然,为 false。
        public virtual bool IsClientConnected();
        //
        // 摘要:
        //     重返一个值,该值提醒是或不是具备诉求数据都可用,以至是或不是没有必要对顾客端举办进一层读取。
        //
        // 再次来到结果:
        //     借使具备央浼数据都可用,则为 true;不然,为 false。
        public virtual bool IsEntireEntityBodyIsPreloaded();
        //
        // 摘要:
        //     重回二个提示连接是或不是接收 SSL 的值。
        //
        // 重返结果:
        //     如若一而再是 SSL 连接,则为 true;不然为 false。私下认可值为 false。
        public virtual bool IsSecure();
        //
        // 摘要:
        //     重临与钦点设想路线相对应的物理路径。
        //
        // 参数:
        //   virtualPath:
        //     设想路线。
        //
        // 再次来到结果:
        //     与 virtualPath 参数中内定的虚构路线相呼应的物理路线。
        public virtual string MapPath(string virtualPath);
        //
        // 摘要:
        //     读取顾客端的央浼数据(在未有预加载时)。
        //
        // 参数:
        //   buffer:
        //     将数据读入的字节数组。
        //
        //   size:
        //     最多读取的字节数。
        //
        // 重临结果:
        //     读取的字节数。
        public virtual int ReadEntityBody(byte[] buffer, int size);
        //
        // 摘要:
        //     使用钦点的要从当中读取数据的缓冲区、字节偏移量和最大字节数从客商端读取乞求数据(当未预先加载时)。
        //
        // 参数:
        //   buffer:
        //     将数据读入的字节数组。
        //
        //   offset:
        //     最早读取之处的字节偏移量。
        //
        //   size:
        //     最多读取的字节数。
        //
        // 重临结果:
        //     读取的字节数。
        public virtual int ReadEntityBody(byte[] buffer, int offset, int size);
        //
        // 摘要:
        //     将 Content-Length HTTP 标头增多到小于或等于 2 GB 的新闻正文的响应。
        //
        // 参数:
        //   contentLength:
        //     响应的尺寸(以字节为单位)。
        public virtual void SendCalculatedContentLength(int contentLength);
        //
        // 摘要:
        //     将 Content-Length HTTP 标头加多到大于 2 GB 的新闻正文的响应。
        //
        // 参数:
        //   contentLength:
        //     响应的长短(以字节为单位)。
        public virtual void SendCalculatedContentLength(long contentLength);
        //
        // 摘要:
        //     将行业内部 HTTP 标头增添到响应。
        //
        // 参数:
        //   index:
        //     标头索引。举例 System.Web.HttpWorkerRequest.HeaderContentLength。
        //
        //   value:
        //     标头的值。
        public abstract void SendKnownResponseHeader(int index, string value);
        //
        // 摘要:
        //     将钦点文件的内容加多到响应并点名文件中的早先地方和要发送的字节数。
        //
        // 参数:
        //   handle:
        //     要发送的文件的句柄。
        //
        //   offset:
        //     文件中的起首地方。
        //
        //   length:
        //     要发送的字节数。
        public abstract void SendResponseFromFile(IntPtr handle, long offset, long length);
        //
        // 摘要:
        //     将钦命文件的剧情加多到响应并点名文件中的早先位置和要发送的字节数。
        //
        // 参数:
        //   filename:
        //     要发送的文本的名称。
        //
        //   offset:
        //     文件中的初阶地点。
        //
        //   length:
        //     要发送的字节数。
        public abstract void SendResponseFromFile(string filename, long offset, long length);
        //
        // 摘要:
        //     将字节数组中钦定数量的字节加多到响应。
        //
        // 参数:
        //   data:
        //     要发送的字节数组。
        //
        //   length:
        //     要发送的字节数(从第几个字节领头)。
        public abstract void SendResponseFromMemory(byte[] data, int length);
        //
        // 摘要:
        //     将内部存款和储蓄器块中钦定数量的字节增添到响应。
        //
        // 参数:
        //   data:
        //     指向内部存款和储蓄器块的非托管指针。
        //
        //   length:
        //     要发送的字节数。
        public virtual void SendResponseFromMemory(IntPtr data, int length);
        //
        // 摘要:
        //     内定响应的 HTTP 状态代码和景观表明,举例 SendStatus(200, "Ok"卡塔尔。
        //
        // 参数:
        //   statusCode:
        //     要发送的情况代码
        //
        //   statusDescription:
        //     要发送的景况表明。
        public abstract void SendStatus(int statusCode, string statusDescription);
        //
        // 摘要:
        //     将非规范 HTTP 标头增加到响应。
        //
        // 参数:
        //   name:
        //     要发送的标头的名称。
        //
        //   value:
        //     标头的值。
        public abstract void SendUnknownResponseHeader(string name, string value);
        //
        // 摘要:
        //     在殡葬全数响应数据后注册可选公告。
        //
        // 参数:
        //   callback:
        //     在出殡和安葬全数数据(带外)后调用的打招呼回调。
        //
        //   extraData:
        //     回调的增大参数。
        public virtual void SetEndOfSendNotification(HttpWorkerRequest.EndOfSendNotification callback, object extraData);

  private string Result 回调状态保持对象,保存响应结果用

        // 摘要:
        //     表示用于在产生发送响应后通报调用方的章程。
        //
        // 参数:
        //   wr:
        //     当前的 System.Web.HttpWorkerRequest。
        //
        //   extraData:
        //     处理乞求所需的其余其余数据。
        public delegate void EndOfSendNotification(HttpWorkerRequest wr, object extraData);
    }

  private bool TimeoutFlag 总超时时间是还是不是过期标记

 

  private int TimeoutTime 总超时时间(包括四次重试),私下认可10s

  private int RetryCount 总U途观L调用(败北)自动重试次数,私下认可3次

  private int WaitSleep 主线程,仿Ajax回调等待时间,暗许10ms

  private int TrySleep 每趟央求地址失败后,重试时间间隔,私下认可2s

  public string GetRemoteData()  解析:

图片 13图片 14

 1             //
 2             var timeNum = 0;
 3             while (true)
 4             {
 5                 if (ResponseFlag)
 6                 {
 7                     break;
 8                 }
 9                 if (TimeoutFlag)
10                 {
11                     throw new Exception(string.Format("请求超时!超时时间:{0}S", TimeoutTime / 1000));
12                 }
13                 timeNum  = WaitSleep;
14                 if (timeNum >= TimeoutTime)
15                 {
16                     TimeoutFlag = true;
17                 }
18                 Thread.Sleep(WaitSleep);
19             }

主线程,仿Ajax回调等待

  private void RemoteNew(Action<Remoter, string> action) 解析:

图片 15图片 16

 1         private void RemoteNew(Action<Remoter, string> action) 
 2         {
 3             //
 4             var reNum = 0;
 5             for (var i = 0; i < this.RetryCount; i  )
 6             {
 7                 try
 8                 {
 9                     // 此处省略
10                     //... ...
11 
12                     //
13                     break;
14                 }
15                 catch (Exception ex)
16                 {
17                     Thread.Sleep(this.TrySleep);
18                     reNum  ;
19                     if (reNum == this.RetryCount)
20                     {
21                         throw new Exception(string.Format("重试失败!重试次数:{0}次,失败原因:{1}", this.RetryCount, ex.Message));
22                     }
23                     continue;
24                 }
25             }
26         }                        

调用U奇骏L退步,自动重试机制

图片 17图片 18

 1                     //
 2                     this.Request.BeginGetResponse((arr) =>
 3                     {
 4                         //
 5                         var state = arr.AsyncState as Remoter;
 6                         //
 7                         var response = state.Request.EndGetResponse(arr) as HttpWebResponse;
 8                         var respStream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("UTF-8"));
 9                         action(state, respStream.ReadToEnd());
10                         respStream.Close();
11                         response.Close();
12                     }, this);

异步响应回调,闭包与自状态保持

   private void SetResult(Remoter state, string jsonData) 解析:

图片 19图片 20

1                 state.Result = jsonData;
2                 state.ResponseFlag = true;

异步响应成功后,在气象保持中赋值结果

四、布署中的开源项目...

    安顿接二连三会将生育中解除难题的多多地点集聚成多个档案的次序【Meng.Net.dll】并开源至GitHub上,迎接沟通,协同进步~~

  至于本文所讲的类会在哪个命名空间中,尚未想好,项指标完好布局及主打方向,敬请期望......

 

                                         蒙

                                    2016-09-24  22:37  周六

 

 

 

       

                    

 

本文由pc28.am发布于计算机编程,转载请注明出处:HttpRuntime的认知与抓好明白,异步HTTP乞请操作

上一篇:手把手教孩子学数独,Noip2009靶形数独 下一篇:没有了
猜你喜欢
热门排行
精彩图文