NET 5 使用HttpClient和HttpWebRequest
HttpWebRequest
这是.NET创建者最初开发用于使用HTTP请求的标准类。HttpWebRequest是老版本.net下常用的,较为底层且复杂,访问速度及并发也不甚理想,但是使用HttpWebRequest可以让开发者控制请求/响应流程的各个方面,如 timeouts, cookies, headers, protocols。另一个好处是HttpWebRequest类不会阻塞UI线程。例如,当您从响应很慢的API服务器下载大文件时,您的应用程序的UI不会停止响应。通常和WebResponse一起使用,一个发送请求,一个获取数据。另外HttpWebRequest库已经过时,不适合业务中直接使用,他更适用于框架内部操作。


/// <summary>
/// HttpWebRequest请求网页示例
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebResponse = null;
Stream responseStream = null;
string url = "https://www.cnblogs.com/";
try
{
httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url); //cookie,cookie一般用来验证登录或是跟踪使用
httpWebRequest.CookieContainer = new CookieContainer();
httpWebRequest.CookieContainer.Add(new Cookie() { Name = "test", Value = "test1",Domain="www.cnblogs.com" }); //来源页面
httpWebRequest.Referer = url; //比较重要的UserAgent
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0 Gecko/20100101 Firefox/52.0"; //请求方法,有GET,POPST,PUT等
httpWebRequest.Method = "GET"; //如果上传文件,是要设置 GetRequestStream
//httpWebRequest.GetRequestStream try
{
httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
}
catch (System.Net.WebException we)
{
///这个说明服务器返回了信息了,不过是非200,301,302这样正常的状态码
if (we.Response != null)
{
httpWebResponse = (HttpWebResponse)we.Response;
}
} ///得到返回的stream,如果请求的是一个文件或图片,可以直接使用或保存
responseStream = httpWebResponse.GetResponseStream(); ///使用utf8方式读取数据流
StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8); ///这里是一次性读取,对于超大的stream,要不断读取并保存
string html = streamReader.ReadToEnd();
streamReader.Close();
responseStream.Close();
Console.WriteLine(html.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (httpWebRequest != null) httpWebRequest.Abort();
if (httpWebResponse != null) httpWebResponse.Close();
if (responseStream != null) responseStream.Close();
}
}
HttpClient
HttpClient提供强大的功能,提供了异步支持,可以轻松配合async await 实现异步请求,使用HttpClient,在并发量不大的情况,一般没有任何问题;但是在并发量一上去,如果使用不当,会造成很严重的堵塞的情况。
平时我们在使用HttpClient的时候,会将HttpClient包裹在using内部进行声明和初始化,
using(var httpClient = new HttpClient())
{
//other codes
}
在高并发的情况下,连接来不及释放,socket被耗尽,耗尽之后就会出现喜闻乐见的一个错误:
Unable to connect to the remote serverSystem.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.
那么如何处理这个问题?“复用HttpClient”即可
- HttpClientFacotry很高效,可以最大程度上节省系统socket。(“JUST USE IT AND FXXK SHUT UP”:P)
- Factory,顾名思义HttpClientFactory就是HttpClient的工厂,内部已经帮我们处理好了对HttpClient的管理,不需要我们人工进行对象释放,同时,支持自定义请求头,支持DNS更新等等等
从微软源码分析,HttpClient继承自HttpMessageInvoker,而HttpMessageInvoker实质就是HttpClientHandler。
HttpClientFactory 创建的HttpClient,也即是HttpClientHandler,只是这些个HttpClient被放到了“池子”中,工厂每次在create的时候会自动判断是新建还是复用。(默认生命周期为2min)
还理解不了的话,可以参考Task和Thread的关系
解决方案如下:
IHttpClientFactory
一、可以参考微软官方提供的方法:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests?view=aspnetcore-5.0
二、我的解决方案是根据官方提供的方法,选择一种最适合项目的写法进行改造。
1、nuget添加包Microsoft.AspNetCore.Http;
2、startup里ConfigureServices方法添加代码:
services.AddHttpClient();
or
public void ConfigureServices(IServiceCollection services)
{
//other codes services.AddHttpClient("client_1",config=> //这里指定的name=client_1,可以方便我们后期服用该实例 比如已经填写url和header
{
config.BaseAddress= new Uri("http://client_1.com");
config.DefaultRequestHeaders.Add("header_1","header_1"); }); services.AddHttpClient(); //other codes
services.AddMvc().AddFluentValidation();
}
3、可以使用依赖项注入 (DI) 来请求 IHttpClientFactory。 以下代码使用 IHttpClientFactory 来创建 HttpClient 实例:(官方demo)
public class BasicUsageModel : PageModel
{
private readonly IHttpClientFactory _clientFactory; public IEnumerable<GitHubBranch> Branches { get; private set; } public bool GetBranchesError { get; private set; } public BasicUsageModel(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
} public async Task OnGet()
{
var request = new HttpRequestMessage(HttpMethod.Get,
"https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
request.Headers.Add("Accept", "application/vnd.github.v3+json");
request.Headers.Add("User-Agent", "HttpClientFactory-Sample"); var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode)
{
using var responseStream = await response.Content.ReadAsStreamAsync();
Branches = await JsonSerializer.DeserializeAsync
<IEnumerable<GitHubBranch>>(responseStream);
}
else
{
GetBranchesError = true;
Branches = Array.Empty<GitHubBranch>();
}
}
}
在实际使用中,我们经常会用NewtonJson序列化,给一个简单的Demo:
string api_domain = _config.GetSection("OuterApi:open-api").Value;
string api_url = $"{api_domain}/common-service/api/basic?code={code}";
var request = new HttpRequestMessage(HttpMethod.Get, api_url);
request.Headers.Add("Accept", "application/vnd.github.v3+json"); var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); Result<List<OpenApiDictModel>> apiRet = new Result<List<OpenApiDictModel>>();
if (response.IsSuccessStatusCode)
{
string responseStr = await response.Content.ReadAsStringAsync();
apiRet = JsonConvert.DeserializeObject<Result<List<OpenApiDictModel>>>(responseStr);
}
NET 5 使用HttpClient和HttpWebRequest的更多相关文章
- WebClient vs HttpClient vs HttpWebRequest
转载:http://www.diogonunes.com/blog/webclient-vs-httpclient-vs-httpwebrequest/ Just when I was startin ...
- c# HttpClient和HttpWebRequest添加Basic类型的Authentication认证
c#项目中用到调用客户接口,basic身份认证,base64格式加密(用户名:密码)贴上代码以备后用 1.使用HttpClient实现basic身份认证 using (HttpClient clien ...
- 如何选择 WebClient,HttpClient,HttpWebRequest
当我们在用 .NET 调用 RestAPI 时通常有三种选择,分别为:WebClient, HttpWebRequest,HttpClient,这篇文章我们将会讨论如何使用这三种方式去调用 RestA ...
- 十二、.net core(.NET 6)添加通用的访问webapi的方法(包括HttpClient和HttpWebRequest)
开发通用的访问webapi方法. 在common工具文件夹下,新建一个类库项目:Wsk.Core.WebHelper,并引用Package包项目,然后新建一个类HttpClientHelper,用于使 ...
- 使用HttpClient实现并发请求
在.Net 4.0之前,一直是依靠HttpWebRequest实现Http操作的.它默认有一个非常保守的同一站点下最大2并发数限制,导致默认情况下HttpWebRequest往往得不到理想的速度,必须 ...
- 关于 C# HttpClient的 请求
Efficiently Streaming Large HTTP Responses With HttpClient Downloading large files with HttpClient a ...
- HttpClient 模拟登陆知乎
最近做爬虫相关工作,我们平时用HttpWebRequest 比较多,每一个Url都要创建一个HttpWebRequest实例, 而且有些网站验证比较复杂,在登陆及后续抓取数据的时候,每次请求需要把上次 ...
- C# HTTP系列1 HttpWebRequest类
系列目录 [已更新最新开发文章,点击查看详细] .NET Framework 中 System.Net 命名空间下提供了 HttpWebRequest 和 HttpWebResponse 2个 ...
- Xamarin.Android之封装个简单的网络请求类
一.前言 回忆到上篇 <Xamarin.Android再体验之简单的登录Demo> 做登录时,用的是GET的请求,还用的是同步, 于是现在将其简单的改写,做了个简单的封装,包含基于Http ...
随机推荐
- Window .NetCore Nginx
1.首先去官网下载Nginx 官网地址:http://nginx.org/en/download.html 2.下载好之后,我的文件是放在D:\InstallFiles\Nginx\nginx-1.1 ...
- 用PyCharm打个专业的招呼
PyCharm 是什么 PyCharm(读作"拍恰姆")是 JetBrains 全家桶中的一员,专门用来写 Python 的: 官方网址是: https://www.jetbrai ...
- C和指针---结构和联合
一.结构 1.C提供了两种类型的聚合数据类型---数组.结构.数组是相同类型的元素集合,它的每个元素长度相同,故可以通过下标引用或指针间接访问来选择的;而结构可以把不同类型的值存储在一起,由于结构的成 ...
- Vmware无法生成本地连接
打开Vmware使用乌班图 结果发现没有办法连接本地连接,那就是注册表出现了问题 今天推荐一个好软件 然后使用进行清理缓存,重新注册表 然后直接点击虚拟机里面的编辑->虚拟网络编辑器->把 ...
- 2017 Mid Central Regional G.Hopscotch (组合计数)
这道题有点意思,给出点(N,N),你在原点处向目标点走,每次只能向x和y两个方向走路,每次xy两个方向的步幅分别不能小于dx和dy,问走到终点的方案数,答案对1e9 + 7取模 这道题最直接的想法就是 ...
- linux下的bash shell
运行bash shell命令的方式 vi t1.sh 并输入 pwd ls pwd 然后:x保存关闭 1.首先查看权限 ls -l,如果没有执行权限则用chmod a+x t1.sh ,最后运行./t ...
- 在执行gem install redis时 : ERROR: Error installing redis: redis requires Ruby version >= 2.2.2
在执行gem install redis时 提示: gem install redis ERROR: Error installing redis: redis requires Ruby versi ...
- Python怎么控制将一个整数输出成指定长的十六进制数?
使用format方法,在格式控制中进行控制,具体控制参数为: {:#016X} 其中: 大括号表示该处从后面的format的参数中取值 冒号表示格式控制开始 0表示长度不足16位补0 16表示长度 X ...
- PyQt(Python+Qt)学习随笔:QScrollArea滚动区域layout布局的作用及设置方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 滚动区域可以设置布局,布局的作用其实与其他布局一样,就是在滚动区域大小调整时,滚动区域内的子部件跟随 ...
- PyQt(Python+Qt)学习随笔:QListWidget插入项的insertItem方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在QListWidget对象中,插入一个项的方法是调用insertItem方法,insertItem ...