【原创-算法-实现】异步HTTP请求操作
索引:
一、说明
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请求操作的更多相关文章
- iOS 多个异步网络请求全部返回后再执行具体逻辑的方法
对于dispatch多个异步操作后的同步方法,以前只看过dispatch_group_async,看看这个方法的说明: * @discussion * Submits a block to a dis ...
- Java利用httpasyncclient进行异步HTTP请求
Java利用httpasyncclient进行异步HTTP请求 前段时间有个需求在springmvc mapping的url跳转前完成一个统计的业务.显然需要进行异步的处理,不然出错或者异常会影响到后 ...
- C# Windows异步I/O操作
1.简介 关于Windows的异步I/O操作,只要解决的是同步I/O操作的线程利用率问题,通过异步I/O Api来提升线程的利用率,提升系统的吞吐能力,将各种I/O操作交给线程池然后交由硬件设备执行, ...
- Android Asynchronous Http Client-Android异步网络请求客户端接口
1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnect,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使用and ...
- PIE SDK算法的异步调用
1.算法功能简介 异步方法一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作.异步方法通常会在另外一个线程中,“真实”地执行着.整个过程,不会阻碍调用者的工作. PIE SDK支持算法功能的执 ...
- iOS开发--用户点击频繁,多个异步网络请求取消问题?
一.业务环境描述 当一个view同时添加两个tableView为subView的时候,两个tableView分别为mainTable和subTable. 当用户点击mainTable上的某一条数据时, ...
- 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 重点: 实现多级子目录的压缩, ...
- 如何解决异步接口请求快慢不均导致的数据错误问题? - DevUI
DevUI 是一款面向企业中后台产品的开源前端解决方案,它倡导沉浸.灵活.至简的设计价值观,提倡设计者为真实的需求服务,为多数人的设计,拒绝哗众取宠.取悦眼球的设计.如果你正在开发 ToB 的工具类产 ...
- Win8开虚拟wifi ‘无法启动承载网络 组或资源的状态不是执行请求操作的正确状态“
第一步,首先我们点开开始按钮菜单,要右键以“管理员身份”打开CMD“命令提示符”并键入或者复制(粘贴)命令:netsh wlan show drivers 查看本机无线网卡是否支持此项Wifi热点共享 ...
随机推荐
- iOS--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook等系统服务开发汇总
iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用系统应用.使用系统服务: ...
- iOS-技巧性总结
1.AFN与ASI对比 -- AFN1. 基于 NSURLConnection & NSURLSession 进行的封装2. 使用简单3. 提供了自动的序列化 & 反序列化支持! AF ...
- HTML5_03之Canvas绘图
1.Canvas绘图--JS绘图: <canvas id='c1' width='' height=''></canvas> * Canvas尺寸不能用CSS设置: c1.he ...
- mock.js
mock.js http://mockjs.com/ https://github.com/nuysoft/Mock/wiki 为了完成angularjs的karma测试,看到这个好东东,这货能拦截a ...
- Css概要与选择器,刻度单位
目录 一.CSS3概要 1.1.特点 1.2.效果演示 1.3.帮助文档与学习 二.选择器 1.1.基础的选择器 1.2.组合选择器 1.3.属性选择器 1.4.伪类 1.5.伪元素 三.特殊性(优先 ...
- Over:窗口函数(滑动聚合)
Over 窗口函数在Select 子句中,对查询的结果集进行“滑动-聚合”运算:如果使用count,那么基于滑动窗口的聚合语义同 base+1 累加:如果使用sum,那么基于滑动窗口的聚合语义等同于数 ...
- ArcGIS API for JavaScript(2)-ArcGIS Server发布要素图层服务
1.前言 上一篇该系列的文章我们主要讲了一下基础Web地图搭建,这篇我们主要讲一下ArcGIS Server发布服务,并且如何调用服务.将自己的数据加载到Web地图当中来,实现Web端浏览数据. 2. ...
- Objective-C中的内存管理
在编程语言中是少不了对内存的管理的,内存对于计算机来说是宝贵的资源,所以对使用不到的资源进行回收是很有必要的.OC中使用引用计数和垃圾回收来管理内存,在OC中为每个对象分配一个引用计数器,当对象刚刚被 ...
- C语言之链表
这两天在复习C语言的知识,为了给下个阶段学习OC做准备,以下的代码的编译运行环境是Xcode5.0版本,写篇博文把昨天复习的C语言有关链表的知识给大家分享一下,以下是小菜自己总结的内容,代码也是按照自 ...
- publishing failed with multiple errors resource is out of sync with the file system--转
原文地址:http://blog.csdn.net/feng1603/article/details/7398266 今天用eclipse部署项目遇到"publishing failed w ...