索引:

目录索引

一、说明

  1) 这个类 是我 在真实项目中,优化解决真实问题 时,不参考第三方代码,完全由自己查阅MSDN官方文档 , 完成的一个真实生产环境中使用的功能类

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

  3) 此代码以【面向对象】、【C#闭包】、【异步回调】、【超时】、【等待】、【自动重试】方式实现及完成,且可以配置扩展

二、代码

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

     /// <summary>
/// 异步 Http
/// </summary>
public class Remoter
{
/*
* LM,2016/08/18
* C#闭包化,异步化,Web操作
* 以便支持POS多接口多操作同时使用
*/ /// <summary>
/// 请求地址
/// </summary>
public string URL { get; set; } /// <summary>
/// 请求方式
/// </summary>
public string RequestMethod { get; set; } /// <summary>
/// 请求数据
/// </summary>
public string JsonContent { get; set; } //
private byte[] Buffer { get; set; }
private Stream RequestStream { get; set; }
private HttpWebRequest Request { get; set; }
private bool ResponseFlag { get; set; }
private string Result { get; set; }
private bool TimeoutFlag { get; set; }
private int TimeoutTime { get; set; }
private bool RetryFlag { get; set; }
private int RetryCount { get; set; }
private int WaitSleep { get; set; }
private int TrySleep { get; set; } // 初始化
public Remoter()
{
//
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback((object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) => true); //
this.URL = string.Empty;
this.Request = default(HttpWebRequest);
this.JsonContent = string.Empty;
this.Buffer = default(byte[]);
this.RequestStream = default(Stream);
this.ResponseFlag = false;
this.Result = string.Empty;
this.TimeoutFlag = false;
this.TimeoutTime = * ;
this.RetryFlag = false;
this.RetryCount = ;
this.WaitSleep = ;
this.RequestMethod = "POST";
this.TrySleep = ;
} /// <summary>
/// 获取响应数据
/// </summary>
public string GetRemoteData()
{
//
if(string.IsNullOrWhiteSpace(this.URL))
{
throw new Exception("HttpAsync.URL,未赋值!");
} //
RemoteNew(SetResult); //
var timeNum = ;
while (true)
{
if (ResponseFlag)
{
break;
}
if (TimeoutFlag)
{
throw new Exception(string.Format("请求超时!超时时间:{0}S", TimeoutTime / ));
}
timeNum += WaitSleep;
if (timeNum >= TimeoutTime)
{
TimeoutFlag = true;
}
Thread.Sleep(WaitSleep);
} //
return Result;
} //
private void RemoteNew(Action<Remoter, string> action)
{
//
var reNum = ;
for (var i = ; i < this.RetryCount; i++)
{
try
{
//
var uri = URL; //
this.Request = WebRequest.Create(uri) as HttpWebRequest;
this.Request.KeepAlive = false;
this.Request.Method = this.RequestMethod;
this.Request.Credentials = CredentialCache.DefaultCredentials;
if (this.RequestMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
{
this.Buffer = Encoding.UTF8.GetBytes(this.JsonContent);
this.Request.ContentLength = this.Buffer.Length;
this.Request.ContentType = "application/json";
this.RequestStream = this.Request.GetRequestStream();
this.RequestStream.Write(this.Buffer, , this.Buffer.Length);
this.RequestStream.Close();
} //
this.Request.BeginGetResponse((arr) =>
{
//
var state = arr.AsyncState as Remoter;
//
var response = state.Request.EndGetResponse(arr) as HttpWebResponse;
var respStream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("UTF-8"));
action(state, respStream.ReadToEnd());
respStream.Close();
response.Close();
}, this);
//
break;
}
catch (Exception ex)
{
Thread.Sleep(this.TrySleep);
reNum++;
if (reNum == this.RetryCount)
{
throw new Exception(string.Format("重试失败!重试次数:{0}次,失败原因:{1}", this.RetryCount, ex.Message));
}
continue;
}
}
}
private void SetResult(Remoter state, string jsonData)
{
if (!string.IsNullOrWhiteSpace(jsonData))
{
state.Result = jsonData;
state.ResponseFlag = true;
}
}
}

Remoter.cs

  使用方式:

  GET: 

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

  POST:

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

三、代码解析

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

             //
this.URL = string.Empty;
this.Request = default(HttpWebRequest);
this.JsonContent = string.Empty;
this.Buffer = default(byte[]);
this.RequestStream = default(Stream);
this.ResponseFlag = false;
this.Result = string.Empty;
this.TimeoutFlag = false;
this.TimeoutTime = * ;
this.RetryFlag = false;
this.RetryCount = ;
this.WaitSleep = ;
this.RequestMethod = "POST";
this.TrySleep = ;

可从配置文件读取部分

  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 TimeoutFlag 总超时时间是否超时标识

  private int TimeoutTime 总超时时间(包含若干次重试),默认10s

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

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

  private int TrySleep 每次请求地址失败后,重试时间间隔,默认2s

  public string GetRemoteData()  解析:

             //
var timeNum = ;
while (true)
{
if (ResponseFlag)
{
break;
}
if (TimeoutFlag)
{
throw new Exception(string.Format("请求超时!超时时间:{0}S", TimeoutTime / ));
}
timeNum += WaitSleep;
if (timeNum >= TimeoutTime)
{
TimeoutFlag = true;
}
Thread.Sleep(WaitSleep);
}

主线程,仿Ajax回调等待

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

         private void RemoteNew(Action<Remoter, string> action)
{
//
var reNum = ;
for (var i = ; i < this.RetryCount; i++)
{
try
{
// 此处省略
//... ... //
break;
}
catch (Exception ex)
{
Thread.Sleep(this.TrySleep);
reNum++;
if (reNum == this.RetryCount)
{
throw new Exception(string.Format("重试失败!重试次数:{0}次,失败原因:{1}", this.RetryCount, ex.Message));
}
continue;
}
}
}

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

                     //
this.Request.BeginGetResponse((arr) =>
{
//
var state = arr.AsyncState as Remoter;
//
var response = state.Request.EndGetResponse(arr) as HttpWebResponse;
var respStream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("UTF-8"));
action(state, respStream.ReadToEnd());
respStream.Close();
response.Close();
}, this);

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

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

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

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

四、计划中的开源项目...

   计划后续会将生产中解决问题的诸多地方汇集成一个项目【Meng.Net.dll】并开源至GitHub上,欢迎交流,共同提高~~

  至于本文所讲的类会在哪个命名空间中,还没想好,项目的整体结构及主打方向,敬请期待......

                                         蒙

                                    2016-09-24  22:37  周六

      

                   

【原创-算法-实现】异步HTTP请求操作的更多相关文章

  1. iOS 多个异步网络请求全部返回后再执行具体逻辑的方法

    对于dispatch多个异步操作后的同步方法,以前只看过dispatch_group_async,看看这个方法的说明: * @discussion * Submits a block to a dis ...

  2. Java利用httpasyncclient进行异步HTTP请求

    Java利用httpasyncclient进行异步HTTP请求 前段时间有个需求在springmvc mapping的url跳转前完成一个统计的业务.显然需要进行异步的处理,不然出错或者异常会影响到后 ...

  3. C# Windows异步I/O操作

    1.简介 关于Windows的异步I/O操作,只要解决的是同步I/O操作的线程利用率问题,通过异步I/O Api来提升线程的利用率,提升系统的吞吐能力,将各种I/O操作交给线程池然后交由硬件设备执行, ...

  4. Android Asynchronous Http Client-Android异步网络请求客户端接口

    1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnect,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使用and ...

  5. PIE SDK算法的异步调用

    1.算法功能简介 异步方法一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作.异步方法通常会在另外一个线程中,“真实”地执行着.整个过程,不会阻碍调用者的工作. PIE SDK支持算法功能的执 ...

  6. iOS开发--用户点击频繁,多个异步网络请求取消问题?

    一.业务环境描述 当一个view同时添加两个tableView为subView的时候,两个tableView分别为mainTable和subTable. 当用户点击mainTable上的某一条数据时, ...

  7. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  8. 如何解决异步接口请求快慢不均导致的数据错误问题? - DevUI

    DevUI 是一款面向企业中后台产品的开源前端解决方案,它倡导沉浸.灵活.至简的设计价值观,提倡设计者为真实的需求服务,为多数人的设计,拒绝哗众取宠.取悦眼球的设计.如果你正在开发 ToB 的工具类产 ...

  9. Win8开虚拟wifi ‘无法启动承载网络 组或资源的状态不是执行请求操作的正确状态“

    第一步,首先我们点开开始按钮菜单,要右键以“管理员身份”打开CMD“命令提示符”并键入或者复制(粘贴)命令:netsh wlan show drivers 查看本机无线网卡是否支持此项Wifi热点共享 ...

随机推荐

  1. Spark读取HBase

    背景:公司有些业务需求是存储在HBase上的,总是有业务人员找我要各种数据,所以想直接用Spark( shell) 加载到RDD进行计算 摘要: 1.相关环境 2.代码例子 内容 1.相关环境 Spa ...

  2. java IO流 之 其他流

    一.内存操作流(ByteArrayInputStream.ByteArrayOutputStream) (一).   public class ByteArrayInputStream extends ...

  3. Python学习路径及练手项目合集

    Python学习路径及练手项目合集 https://zhuanlan.zhihu.com/p/23561159

  4. SSISDB7:查看当前正在运行的Package

    在项目组中做ETL开发时,经常会被问到:“现在ETL跑到哪一个Package了?” 为了缩短ETL运行的时间,在ETL的设计上,经常会使用并发执行模式:Task 并发执行,Package并发执行.对于 ...

  5. OleDb Source component 用法

    OleDb Source component 主要是从DB中获取数据,传递给下游组件,OleDb Source component的强大之处在于 query data 的mode有四种,如图 Tabl ...

  6. 部署 instance 到 VXLAN - 每天5分钟玩转 OpenStack(112)

    上一节我们创建了 vxlan 100_net,今天将部署 instance 并分析网络的连通性. launch 新的 instance "cirros-vm1",网络选择 vxla ...

  7. Linux安装Node.js

    安装环境:Ubuntu:x86_64 Node.js 官网:https://nodejs.org 下载Node.js: wget https://nodejs.org/dist/v4.4.3/node ...

  8. Java 8新特性-4 方法引用

    对于引用来说我们一般都是用在对象,而对象引用的特点是:不同的引用对象可以操作同一块内容! Java 8的方法引用定义了四种格式: 引用静态方法     ClassName :: staticMetho ...

  9. Rust初步(五):Rust与C#性能比较

    我学习Rust的目的并不是说期望用它来取代掉现有的开发平台或语言.相反,我认为当前绝大部分研发团队,都不可能只用一个平台或者一个语言. 当组织增长,他们越来越依赖大量的编程语言.不同的编程语言有不同的 ...

  10. geotrellis使用(十七)使用缓冲区分析的方式解决单瓦片计算边缘值问题

    Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 需求分析 实现方案 总结 一.前言        最 ...