【原创-算法-实现】异步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热点共享 ...
随机推荐
- Spark算子选择策略
摘要 1.使用reduceByKey/aggregateByKey替代groupByKey 2.使用mapPartitions替代普通map 3.使用foreachPartitions替代forea ...
- Android笔记——提升ListView的运行效率
之所以说 ListView 这个控件很难用,就是因为它有很多的细节可以优化,其中运行效率就是很重要的一点.目前我们ListView 的运行效率是很低的,因为在 FruitAdapter 的getVie ...
- window下Nodejs的部署
nodejs http://nodejs.org/#download npm node cli.js install npm -gf //可以安装最新版的NPM node cli.js install ...
- JAVA基础代码分享--DVD管理
问题描述 为某音像店开发一个迷你DVD管理器,最多可存6张DVD,实现碟片的管理. 管理器具备的功能主要有: 1.查看DVD信息. 菜单选择查看功能,展示DVD的信息. 2.新增DVD信息 选择新增功 ...
- Mac下有道笔记本问题反馈
1).Mac笔记上的编辑状态框非常的小.操作起来不是非常的方便.可以把显示稍微放大一些. 2). 新建笔记本的时候,这里用户可能没有注意到这里可以输入,此时这里的高亮的颜色可以适当的修改成别的颜色. ...
- 图的广度优先搜索(BFS)
把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...
- 学习总结之 WebApi 用户登录和匿名登录,及权限验证
近些天,看了一些博客园大牛关于webApi项目的的文章,也有请教师兄一些问题,自己做了个Demo试了试,收获甚多.感谢感谢,下面是我一些学习的总结,如若有错的地方请多多指教!! WebApi登陆与身份 ...
- C# 提取Word文档中的图片
C# 提取Word文档中的图片 图片和文字是word文档中两种最常见的对象,在微软word中,如果我们想要提取出一个文档内的图片,只需要右击图片选择另存为然后命名保存就可以了,今天这篇文章主要是实现使 ...
- Microsoft.Office.Interop.Word 创建word
Microsoft.Office.Interop.Word 创建word 转载:http://www.cnblogs.com/chenbg2001/archive/2010/03/14/1685746 ...
- Android之debug---menu的getActionView()return null
MainActivity代码 @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this a ...