【原创-算法-完结】异步HTTP请求操作

一、说明

  1) 那几个类 是本人 在真正项目中,优化解决真正问题时,不参照第三方代码,完全由友好查阅MSDN官方文档 ,
完结的一个实在生产条件中利用的功能类

  2) 读者在动用此类时,请尊重原创,在代码中添加原创注释://  Author —
Meng.NET (cnblogs.com)  ,同时欢迎 二次改良、二次作文 以共同进步

  3)
此代码以【面向对象】、【C#闭包】、【异步回调】、【超时】、【等待】、【自动重试】方式贯彻及落成,且可以布置伸张

二、代码

  废话不多说,上干货,代码如下:

图片 1图片 2

  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     }

Remoter.cs

  使用方法:

  GET: 

图片 3图片 4

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

View Code

  POST:

图片 5图片 6

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

View Code

三、代码解析

    public Remoter()
初叶化本类,可布置到 App.config/Web.config 中

图片 7图片 8

 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;

可从布署文件读取部分

  public string URL
要呼吁的地点

  public string
RequestMethod HTTP 动词

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

  private byte[]
Buffer 设置请求流的byte数组

  private Stream
RequestStream 请求流

  private HttpWebRequest
Request HTTP请求对象

  private bool
ResponseFlag 与请求对应的响应是或不是中标标识

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

  private bool
提姆eoutFlag 总超时时间是或不是过期标识

  private int
提姆eout提姆e 总超时时间(包涵若干次重试),默许10s

  private int
RetryCount 总URL调用(战败)自动重试次数,默许3次

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

  private int TrySleep
每一遍请求地址败北后,重试时间距离,默许2s

  public string
GetRemoteData()  解析:

图片 9图片 10

 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) 解析:

图片 11图片 12

 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         }                        

调用URL失利,自动重试机制

图片 13图片 14

 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) 解析:

图片 15图片 16

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

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

四、布置中的开源项目…

  
 布置继续会将生产中化解难点的洋洋地点汇聚成一个门类【Meng.Net.dll】并开源至GitHub上,欢迎沟通,共同进步~~

  至于本文所讲的类会在哪个命名空间中,还没想好,项目标完好布局及主打方向,敬请期待……

 

                                         蒙

                                    2016-09-24
 22:37  周六

 

 

 

       

                    

 

相关文章