【原创-算法-实现】异步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热点共享 ...
随机推荐
- KnockoutJS 3.X API 第八章 映射(mapping)插件
Knockout旨在允许您将任意JavaScript对象用作视图模型. 只要一些视图模型的属性是observables,您可以使用KO将它们绑定到您的UI,并且UI将在可观察属性更改时自动更新. 大多 ...
- Leetcode-190 Reverse Bits
#190. Reverse Bits Reverse bits of a given 32 bits unsigned integer. For example, given input 432615 ...
- Oracle_多表查询
SQL多表查询 等值和不等值连接查询 从多个表中获取数据:如果在查询的时候,直接从多个表中获取数据.没有添加条件判断,会出现"笛卡尔积"错误 笛卡尔积错误 笛卡尔集会在下面条件下产 ...
- Ubuntu杂记——Ubuntu下安装VMware
转战Ubuntu,不知道能坚持多久,但是自己还是要努力把转战过程中的学习到的给记录下来.这次就来记录一下,Ubuntu下如何安装VMware. 就我所知,Linux下有VirtualBox和VMwar ...
- JavaScript sync and async(同步和异步)
推荐四篇文章: JavaScript 是单线程的深入分析 JavaScript 运行机制详解:再谈 Event Loop JavaScript 异步编程的4种方法 JavaScript 既是单线程又是 ...
- C#中构造函数的作用
C#中构造函数的作用 共同点: 都是实例化对象,初始化数据的 默认构造是说所有的类都从祖先object那继承了空参的构造方法,你不写与写空参构造都存在,而有参数的构造一般是自己写的,写就有不写就没有, ...
- UIScrollView的delaysContentTouches与canCencelContentTouches属性
UIScrollView有一个BOOL类型的tracking属性,用来返回用户是否已经触及内容并打算开始滚动,我们从这个属性开始探究UIScrollView的工作原理: 当手指触摸到UIScrollV ...
- 相克军_Oracle体系_随堂笔记016-参数文件及数据库的启动和关闭
参数文件: spfile<SID>.ora 动态参数文件,是二进制文件,9i以后引入并建议使用 init<SID>.ora 静态参数文件,是文本文件 动态参数,部分 ...
- 利用简洁的图片预加载组件提升h5移动页面的用户体验
在做h5移动页面,相信大家一定碰到过页面已经打开,但是里面的图片还未加载出来的情况,这种问题虽然不影响页面的功能,但是不利于用户体验.抛开网速的原因,解决这个问题有多方面的思路:最基本的,要从http ...
- 基于STM32Cube的ADC模数采样设计
1.背景 此实验建立在STM32F429核心板基础上,对于深刻了解STM32Cube使用具有深刻意义.利用DMA进行ADC采样,具有速度快,极大减少CPU消耗的优势,对于数据采集系统具 ...