irpas技术客

c#:HttpClient使用详解_jackletter_c# httpclient

网络 894

环境:

window10vs2019.netcore 3.1centos 7.6 一、在c#中发送http请求的方式

本部分参考:《WebClient, HttpClient, HttpWebRequest ,RestSharp之间的区别与抉择》

在c#中常见发送http请求的方式如下:

HttpWebRequest:

.net 平台原生提供,这是.NET创建者最初开发用于使用HTTP请求的标准类。使用HttpWebRequest可以让开发者控制请求/响应流程的各个方面,如 timeouts, cookies, headers, protocols。 . 关于使用HttpWebRequest上传和下载文件,可参考:《c#使用Http上传下载文件》

WebClient:

.net 平台原生提供,WebClient是一种更高级别的抽象,是HttpWebRequest为了简化最常见任务而创建的,但也因此缺少了HttpWebRequest的灵活性。

HttpClient:

.net 平台原生提供,也是这次主讲的内容。

RestSharp:

开源项目,它是基于HttpWebRequest做的二次封装,这里不再说明,可参考:《c#: 使用restsharp发送http请求、下载文件》。

Flurl:

开源项目,基于HttpClient做的二次封装,项目地址:https://github.com/tmenier/Flurl

在.net core平台下推荐使用HttpClient。

二、HttpClient介绍

本部分参考: 《MSDN: SocketsHttpHandler 》

在System.Net.Http命名空间下的HttpClient是.net core平台最常用的http请求工具,它直接基于Socket开发,提供了异步友好的代码编写方式。

下面是简单示例: 看样子使用起来挺简单的。其实隐藏了一些细节,如果我们要对这些细节进行配置的话,建议写成下面的形式:

// 在.net core 2.1之后,默认所有的http请求都会交给SocketsHttpHandler处理 var socketsHttpHandler = new SocketsHttpHandler() { AllowAutoRedirect = true,// 默认为true,是否允许重定向 MaxAutomaticRedirections = 50,//最多重定向几次,默认50次 //MaxConnectionsPerServer = 100,//连接池中统一TcpServer的最大连接数 UseCookies = false// 是否自动处理cookie }; var client = new HttpClient(socketsHttpHandler); 三、HttpClient相关的类 HttpClient类:提供用户调用的入口;HttpRequestMessage类:表示用户请求消息;HttpResponseMessage类:表示http响应消息;

上面是我们最常见的类,除此之外还有:

HttpMessageInvoker:表示发起http消息的入口,HttpClient类就是继承了它,但也仅有HttpClient继承它;HttpMessageHandler:虽然HttpMessageInvoker表示http消息的入口,但发送http消息还要靠HttpMessageHandler,事实上,HttpMessageInvoker内部就封装者一个HttpMessageHandler;SocketsHttpHandler:继承HttpMessageHandler,它是.net core2.1之后事实上的HttpMessageHandler,也就是说我们代码中发送http消息基本用的就是它;HttpClientHandler:也继承自HttpMessageHandler,但其内部封装者SocketsHttpHandler,一般情况下http请求是转发给内部的SocketsHttpHandler处理的;DelegatingHandler:也继承自HttpMessageHandler,不过它是一个抽象类,旨在提供一个http请求管道的基类; 四、HttpClient使用时的注意事项

HttpClient类旨在提供一个用户入口,其内部管理着不同服务器的TCP连接池,如下图所示:

所以,当我们需要发起http请求时,最好使用全局单例的HttpClient,而不是每次都new一个HttpClient。

另外,由于TCP本身在断开连接的时候需要4次挥手动作,而其中又有一个等待时间,所以我们即使将HttpClient.Dispose()掉也会造成这个TCP连接短时间内无法断开(最长要持续4分钟),如果遇到高并发的话,很可能端口就不够用了。正是因为这个原因,微软又出了一个IHttpClientFactory帮助我们建立可复用的HttpClient。

注意:上面缓存连接的时候是以传入的地址前缀做key,而不是最终解析的ip地址,所以,HttpClient对DNS解析不太友好。 HttpClient是线程安全的,里面封装了链接池,使用DnSpy验证如下:

五、HttpClient的使用配置

当我们发送http请求时,我们需要关注一些事情,比如:

是否自动处理cookie;

默认HttpClient是自动处理cookie的,即:上一个请求返回的cookie,可能会随着下次请求发送出去。 然而,最佳的使用方式是多次请求使用相同的HttpClient所以这个cookie隔离性就很差,我们可以在创建HttpClient的时候进行配置禁用cookie自动处理:

var socketsHttpHandler = new SocketsHttpHandler() { UseCookies = false,// 是否自动处理cookie }; var client = new HttpClient(socketsHttpHandler);

是否自动重定向以及最多重定向几次;

默认HttpClient自动处理重定向请求,并且最多重定向50次,一般我们不需要修改这个配置,但我们做测试的话,可以向下面写法:

var socketsHttpHandler = new SocketsHttpHandler() { AllowAutoRedirect=true,//是否自动重定向 MaxAutomaticRedirections=50//自动重定向的最大次数 }; var client = new HttpClient(socketsHttpHandler);

内部TCP链接池的设置;

这个地方有三个配置项:

MaxConnectionsPerServer: 每个url(如:http://·/topic/3951198

比如:

var req = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(url), }; req.Headers.Add("Authorization", "test:123"); // System.FormatException:“The format of value 'test:123' is invalid.”

解决办法:使用 req.Headers.TryAddWithoutValidation("Authorization","test:123")


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #C #httpclient #31centos