HttpClient学习记录

HttpClient 类

提供一个类,用于从 URI 标识的资源发送 HTTP 请求和接收 HTTP 响应。

参考官方文档学习记录

注意事项

  1. HttpClient 旨在实例化一次,并在应用程序的整个生命周期内重复使用。如果为每个请求实例化 HttpClient 类,则重负载下可用的套接字数将耗尽。 这种耗尽将导致 SocketException 错误。
  2. 释放 HttpClient 实例会关闭打开的连接并取消所有挂起的请求。
  3. 每个 HttpClient 实例,都管理着自己的 TCP 连接池,该连接池可以在处理程序中配置连接池中 TCP 连接的数量,空闲的时间,生命周期

构造函数

HttpClient ()
HttpClient (HttpMessageHandler handler)
HttpClient (HttpMessageHandler handler, bool disposeHandler)

参数介绍:

  • HttpMessageHandler :HTTP 消息处理程序的基类。
  • disposeHandler:表示是否在释放 HttpClient 实例时,同时释放 HttpMessageHandler ,如果想重用该处理程序就设置为 false,释放设置为 true

常用方法(目前默认的请求方法都是异步的,也是线程安全的)

Dispose ():释放产生的所有资源。
CancelPendingRequests ():取消 HttpClient 实例所有挂起的请求。
GetAsync (string url):以异步操作将 GET 请求发送给指定 URI。
PostAsync (String url, HttpContent content):以异步操作将 Post 请求发送给指定 URI。
SendAsync (HttpRequestMessage request):以异步操作发送 HTTP 请求。

  • HttpContent :表示请求体的积累
  • HttpRequestMessage : 表示一条 HTTP 请求消息。

常用属性

BaseAddress:发送请求时使用的 Internet 资源的统一资源标识符 (URI) 的基址。例如:http://127.0.0.1:5500/ ,地址从协议名到端口号后面的一个斜杠,在发送请求时请求会将基址与请求的 url 组合起来以创建绝对 URI。
DefaultRequestHeaders:获取与每个请求一起发送的标题。设置默认的请求头,此属性上设置的标头不需要再次在请求消息上设置。
DefaultRequestVersion :获取或设置对此 HttpClient 实例发出的后续请求使用的默认 HTTP 版本,默认值 HttpVersion.Version11。
Timeout:为来自 HttpClient 实例的所有 HTTP 请求设置默认超时,默认是 100s,如果要设置为无限超时,可以将该属性设置为 TimeOut.InfiniteTimeSpan,建议不要设置为无限长
MaxResponseContentBufferSize :获取或设置读取响应内容时要缓冲的最大字节数,默认值为 2GB,返回的内容大小超过了该值就会抛出异常

一般情况下只需要设置 BaseAddress 的值即可

使用示例

static void Main(string[] args)
{
    var client = new HttpClient()
    {
        BaseAddress = new Uri("http://localhost:5500/"),
        DefaultRequestVersion = HttpVersion.Version11,
        MaxResponseContentBufferSize = 1024 * 1024
    };
    client.DefaultRequestHeaders.Add("test", "123");
}
SocketsHttpHandler 类

由 HttpClient 使用的默认消息处理程序,该类继承 HttpMessageHandler,.net core2.1 版本以上使用该类作为 HttpClient 的处理程序,还有其他的处理程序类,推荐使用该类

常用的属性

AutomaticDecompression :获取或设置处理程序用于自动解压缩 HTTP 内容响应的解压缩方法类型。默认是不开启解压缩的,建议不设置
ConnectTimeout :建立 tcp 连接超时时间,默认值是 TimeOut.InfiniteTimeSpan 无限长,建议不设置
MaxConnectionsPerServer :获取或设置允许向单个服务器连接的最大并行 TCP 连接数。(单个服务器指的是同一 域名),当请求数量超过该值,就会排队等待空闲的 tcp 连接,默认是 int.MaxValue,一般不用设置
PooledConnectionIdleTimeout :获取或设置池中连接的最大空闲时间。(发送请求后如果在最大空闲时间内没有再次发送该请求,那么 tcp 连接就会释放掉,该 tcp 连接就可以被其他请求使用) .net6 以上默认值为 1 分钟,.net6 以下为 2 分钟
PooledConnectionLifetime :每个 TCP 链接从创建开始存活的时间,默认是 TimeOut.InfiniteTimeSpan 无限长的,一般也不用设置这个参数;
UseCookies :获取或设置一个值,该值指示处理程序是否应使用 Cookie。上一个请求返回的 cookie,可能会随着下次请求发送出去。
然而,最佳的使用方式是多次请求使用相同的 HttpClient 所以这个 cookie 隔离性就很差,我们可以在创建 HttpClient 的时候进行配置禁用 cookie 自动处理,默认值为 true,建议设置为 false。

常用方法

Dispose ():释放产生的所有资源。

如果在实例化 HttpClient 时设置了 disposeHandler 属性为 true,就会在释放 HttpClient 时自动释放 SocketsHttpHandler 实例,就不需要调用该方法了

使用示例

var socketsHttpHandler = new SocketsHttpHandler()
{
    UseCookies = false,
    AutomaticDecompression = DecompressionMethods.None,
    ConnectTimeout = Timeout.InfiniteTimeSpan,
    MaxConnectionsPerServer = 10,
    PooledConnectionIdleTimeout = TimeSpan.FromMinutes(1),
    PooledConnectionLifetime = Timeout.InfiniteTimeSpan
};
var client = new HttpClient(socketsHttpHandler,true)
{
    BaseAddress = new Uri("http://localhost:5500/"),
};
HttpCompletionOption 枚举

指示 HttpClient 操作是在响应可利用时立即视为已完成,还是在读取包含上下文的整个答案信息之后才视为已完成。

枚举值

ResponseContentRead:返回整个响应内容之后完成。默认值,一般不设置
ResponseHeadersRead:返回响应头之后完成。

使用示例

var client = new HttpClient(socketsHttpHandler, true)
{
    BaseAddress = new Uri("http://localhost:5500/"),
};

var res = await client.GetAsync("", HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
HttpContent 类

表示 HTTP 实体正文和内容标头的基类。该类型是抽象类型,可以使用派生类有:

ByteArrayContent:提供基于字节数组的 HTTP 内容。
FormUrlEncodedContent:使用应用程序/x-www-form-urlencoded MIME 类型编码的名称/值元组的容器。
StringContent:基于字符串提供 HTTP 内容。
JsonContent:提供基于 JSON 的 HTTP 内容。
MultipartContent:提供 HttpContent 对象的集合,其可通过使用多部分/* 内容类型规范序列化。
MultipartFormDataContent:为使用 multipart/form-data MIME 类型进行编码的内容提供容器。
ReadOnlyMemoryContent:提供基于 ReadOnlyMemory 的 HTTP 内容。
StreamContent:基于流提供 HTTP 内容。

常用的方法

ReadAsStringAsync ():将 HTTP 内容序列化到字符串,此为异步操作。
ReadAsStreamAsync ():将 HTTP 内容序列化并返回将内容表示为异步操作的流。
ReadAsByteArrayAsync ():将 HTTP 内容序列化到字节数组,此为异步操作。
CopyToAsync (Stream):将 HTTP 内容序列化为字节流,并将其复制到作为 stream 参数提供的流对象。
CreateContentReadStreamAsync ():采用异步操作将 HTTP 内容序列化到内存流。

ByteArrayContent 使用示例(发送给服务端一张图片)

var client = new HttpClient()
{
    BaseAddress = new Uri("http://127.0.0.1:5500/"),
};

var url = "UserManage/User/Test";
var bytes = await File.ReadAllBytesAsync(@"C:\Users\15423\Pictures\Screenshots\1.png").ConfigureAwait(false);
var content = new ByteArrayContent(bytes);
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
using HttpResponseMessage response = await client.PostAsync(url, content).ConfigureAwait(false);

Console.ReadKey();

服务端保存到桌面

[HttpPost]
public async void Test()
{
    var file = new FileStream(@"C:\Users\15423\Desktop\1.png", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write);
    await Request.Body.CopyToAsync(file);
    file.Dispose();
}

StringContent 使用示例

var json = JsonConvert.SerializeObject(new { Name = "hello" });
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
using HttpResponseMessage response = await client.PostAsync("", content).ConfigureAwait(false);
Content-Type 介绍

表示请求和响应中的媒体类型信息。它用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析并展示 html 等等。

Content-Type 的类型介绍,参考菜鸟教程

HttpResponseMessage 类

表示包括状态代码和数据的 HTTP 响应消息。

常用的 http 请求方法,一般返回类型都是 Task<HttpResponseMessage> 类型,例如:

  • GetAsync
  • DeleteAsync
  • PostAsync
  • PutAsync
  • SendAsync

常用的属性

Content:HttpContent 类型,获取或设置 HTTP 响应消息的内容。
Headers:HttpResponseHeaders 类型,获取 HTTP 响应标头的集合。
IsSuccessStatusCode:bool 类型,获取一个值,该值指示 HTTP 响应是否成功。
StatusCode:HttpStatusCode 枚举类型,获取或设置 HTTP 响应的状态代码,一般判断该属性等于 HttpStatusCode.Ok 就表示请求成功了

常用方法

Dispose():释放与该实例有关的所有的资源
EnsureSuccessStatusCode():如果 HTTP 响应的 IsSuccessStatusCode 属性是 false,则引发异常,如果调用成功,HTTP 则响应消息。

使用示例

var client = new HttpClient()
{
    BaseAddress = new Uri("http://www.baidu.com/"),
};
using HttpResponseMessage response = await client.GetAsync("").ConfigureAwait(false);
if (response != null)
{
    if (response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.OK)
    {
        var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        if (string.IsNullOrEmpty(data))
        {
            Console.WriteLine(data);
        }
    }
}
Console.ReadKey();

释放建议使用 using,也可以使用 Dispose()方法

HttpRequestMessage 类

表示一条 HTTP 请求消息。该类只用于使用 SendAsync() 方法异步发送的 http 请求

常用构造函数

HttpRequestMessage ()
HttpRequestMessage (HttpMethod method, String requestUri)

参数介绍:

  • method :enum 类型,设置 HTTP 请求的方法,例如 HttpMethod.Get,HttpMethod.Post,因此使用该类可以发送任何请求方法
  • requestUri:一个表示请求 Uri 的字符串。

常用的属性

Content:HttpContent 类型,获取或设置 HTTP 消息的内容。
Headers:HttpRequestHeaders 类型,获取 HTTP 请求标头的集合。
Method:HttpMethod 类型,获取或设置 HTTP 请求消息使用的 HTTP 方法。
RequestUri:Uri 枚举类型,获取或设置用于 HTTP 请求的 Uri。

常用方法

Dispose():释放与该实例有关的所有的资源

使用示例放到 SendAsync() 方法的使用方式中

Get 请求

在 HttpClient 中的 Get 请求方法有以下几种(常用方法就是 GetAsync)

GetAsync():返回 HttpResponseMessage 类型,表示异步操作的任务对象。
GetByteArrayAsync():返回 byte[] 类型
GetStreamAsync():返回 Stream 类型
GetStringAsync():返回 string 类型

GetAsync 示例

var client = new HttpClient()
{
    BaseAddress = new Uri("http://127.0.0.1:5500/"),
};
var url = "UserManage/User/TestGet";
using var response = await client.GetAsync(url).ConfigureAwait(false);
if (response != null && response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.OK)
{
    var res = await response.Content.ReadAsStringAsync();
    Console.WriteLine(res);
}

GetByteArrayAsync 示例

var response = await client.GetByteArrayAsync(url).ConfigureAwait(false);
foreach (var item in response)
{
    Console.WriteLine(item);
}
Console.WriteLine(Encoding.UTF8.GetString(response));

GetStreamAsync 示例

var response = await client.GetStreamAsync(url).ConfigureAwait(false);
var memory = new MemoryStream();
await response.CopyToAsync(memory);
memory.Seek(0, SeekOrigin.Begin);
var bytes = new byte[memory.Length];
memory.Read(bytes, 0, bytes.Length);

response.Dispose();
memory.Dispose();
Console.WriteLine(Encoding.UTF8.GetString(bytes));

GetStringAsync 示例

var response = await client.GetStringAsync(url).ConfigureAwait(false);
Console.WriteLine(response);
Post 请求

Post 请求不会阻止。

PostAsync ():返回 HttpResponseMessage 类型,表示异步操作的任务对象。

使用示例

var client = new HttpClient()
{
    BaseAddress = new Uri("http://127.0.0.1:5500/"),
};
var url = "UserManage/User/TestPost";
var content = new StringContent("", Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content).ConfigureAwait(false);
if (response != null && response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.OK)
{
    var res = await response.Content.ReadAsStringAsync();
    Console.WriteLine(res);
}
Console.ReadKey();
SendAsync ()方法使用(推荐使用)

使用 SendAsync ()方法发送 http 请求可以发送所有类型的 http 请求方法,比如 Get、Post 等,使用 SendAsync ()方法要搭配 HttpRequestMessage 使用

SendAsync (HttpRequestMessage request):返回 HttpResponseMessage 类型,表示异步操作的任务对象。

发送 Get 请求示例

var client = new HttpClient()
{
    BaseAddress = new Uri("http://127.0.0.1:5500/"),
};
var url = "UserManage/User/TestGet";
var content = new StringContent("", Encoding.UTF8, "application/json");

var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Content = content;
request.Headers.Add("Authorization", "Bearer xxxx");

var response = await client.SendAsync(request).ConfigureAwait(false);
if (response != null && response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.OK)
{
    var res = await response.Content.ReadAsStringAsync();
    Console.WriteLine(res);
}
Console.ReadKey();

发送 Post 请求示例

var client = new HttpClient()
{
    BaseAddress = new Uri("http://127.0.0.1:5500/"),
};
var url = "UserManage/User/TestPost";
var content = new StringContent("", Encoding.UTF8, "application/json");

var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Content = content;
request.Headers.Add("Authorization", "Bearer xxxx");

var response = await client.SendAsync(request).ConfigureAwait(false);
if (response != null && response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.OK)
{
    var res = await response.Content.ReadAsStringAsync();
    Console.WriteLine(res);
}
Console.ReadKey();

发送 http 请求时,推荐使用 SendAsync ()方法,当发送 get 请求需要使用请求头时,只能使用该方法了

posted @ 2023-09-27 16:13  青蛙001  阅读(260)  评论(0)    收藏  举报