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 ...
随机推荐
- pip更新报错问题
pip更新错误如下: WARNING: You are using pip version 20.1.1; however, version 20.2 is available. You should ...
- python搭建本地共享文件服务器
1.安装python 去官网下载python最新版,然后安装配置好环境 2.运行命令 在终端上输入以下命令 python3 -m http.server 当你执行完这个命令的时候,你的电脑会监听 80 ...
- 「实验课选题详解」用C语言实现万年历
题目要求 编程实现万年历,要求: 可根据用户输入或系统日期进行初始化,如果用户无输入则显示系统日期所在月份的月历,并突出显示当前日期: 可根据用户输入的日期查询,并显示查询结果所在月份的月历,突出显示 ...
- C/C++面试题:C++与C有什么不同?
昨天,小编在一个讨论群里看到这样的对话 有人想要入学校编程俱乐部,面试时,学长问了她C++的区别,她没有答上来,就没有通过. 说到C和C++的区别,不只是进入学校社团有考核,出了学校,找工作面 ...
- PowerManagerService流程分析
一.PowerManagerService简介 PowerManagerService主要服务Android系统电源管理工作,这样讲比较笼统,就具体细节上大致可以认为PowerManagerServi ...
- CentOS下的IPMI尝试
1.载入支持 ipmi 功能的系统模块 modprobe ipmi_msghandler modprobe ipmi_devintf modprobe ipmi_poweroff modprobe i ...
- shiro利用过期时间,解决用户冻结踢出问题
背景 shiro中需要冻结某个用户,但是此时此刻这个用户在线,如果冻结只是改变状态的话,只会导致用户不满,所以要改变这个办法. 在查找过程中发现都是告诉shiro写自定义过滤器,那么我如果自定义过滤器 ...
- JZOJ 2020.10.6 【NOIP2017提高A组模拟9.7】简单无向图
简单无向图 题目 Description Input Output Sample Input 输入1: 4 2 1 1 2 输入2: 10 2 2 2 2 1 1 2 1 1 2 Sample Out ...
- day4(JWT介绍)
1.JWT介绍 1.1jwt原理 最简单理解:jwt本质就是, 把用户信息通过加密后生成的一个字符串 JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户 { "Use ...
- PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox增加自定义按钮的方法
在Qt Designer中可以预先定义标准按钮,相关支持的标准按钮请见<PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的StandardButton ...