使用httpclient时需复用实例或使用httpclientfactory管理生命周期。1.避免为每个请求创建新httpclient实例,以防止端口耗尽和dns解析浪费;2.推荐将httpclient声明为静态或使用httpclientfactory进行依赖注入,以实现连接复用并解决dns缓存问题;3.httpclientfactory通过管理httpmessagehandler的生命周期,既提升性能又确保dns更新及时生效。

HttpClient
使用C#的
HttpClient
HttpClient
HttpRequestMessage
HttpClient
HttpClient
HttpClientFactory
我们来看一个发送GET请求的例子。假设你需要从某个API获取数据:
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class HttpRequestSender
{
// 推荐的做法:复用HttpClient实例
// 实际项目中,更推荐使用HttpClientFactory
private static readonly HttpClient _httpClient = new HttpClient();
public async Task GetExampleAsync(string url)
{
try
{
// 发送GET请求并等待响应
HttpResponseMessage response = await _httpClient.GetAsync(url);
// 确保请求成功(状态码2xx)
response.EnsureSuccessStatusCode();
// 读取响应内容
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"GET 请求成功,响应内容:\n{responseBody}");
}
catch (HttpRequestException e)
{
Console.WriteLine($"GET 请求出错: {e.Message}");
// 这里可以根据e.StatusCode进行更细致的错误处理
}
catch (TaskCanceledException e) when (e.InnerException is TimeoutException)
{
Console.WriteLine($"GET 请求超时: {e.Message}");
}
catch (Exception e)
{
Console.WriteLine($"发生未知错误: {e.Message}");
}
}
public async Task PostExampleAsync(string url, string jsonContent)
{
try
{
// 准备POST请求的内容
StringContent content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
// 发送POST请求
HttpResponseMessage response = await _httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode(); // 检查状态码
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"POST 请求成功,响应内容:\n{responseBody}");
}
catch (HttpRequestException e)
{
Console.WriteLine($"POST 请求出错: {e.Message}");
}
catch (Exception e)
{
Console.WriteLine($"发生未知错误: {e.Message}");
}
}
}
// 调用示例
/*
public class Program
{
public static async Task Main(string[] args)
{
HttpRequestSender sender = new HttpRequestSender();
// 假设这是一个真实存在的API地址
await sender.GetExampleAsync("https://jsonplaceholder.typicode.com/todos/1");
string postData = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
await sender.PostExampleAsync("https://jsonplaceholder.typicode.com/posts", postData);
}
}
*/这段代码展示了
HttpClient
async
await
这是一个老生常谈但又极其关键的问题。许多开发者,包括我自己在初学时,都曾陷入为每个请求创建新
HttpClient
HttpClient
SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted
正确的姿势是复用HttpClient
HttpClient
然而,长期复用一个
HttpClient
HttpClient
HttpClient
为了解决这个DNS缓存和生命周期管理的平衡问题,.NET Core 2.1及更高版本引入了IHttpClientFactory
HttpClient
IHttpClientFactory
HttpClient
HttpClient
HttpMessageHandler
HttpMessageHandler
IHttpClientFactory
HttpMessageHandler
在ASP.NET Core应用中,你通常会在
Startup.cs
ConfigureServices
// 在Startup.cs的ConfigureServices方法中
services.AddHttpClient(); // 注册默认的HttpClient
// 或者注册一个具名客户端
services.AddHttpClient("myApi", client =>
{
client.BaseAddress = new Uri("https://api.example.com/");
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
// 还可以注册一个类型化客户端
services.AddHttpClient<MyApiService>(); // MyApiService会通过构造函数注入HttpClient然后,在你的服务类中通过构造函数注入
HttpClient
IHttpClientFactory
HttpClient
HttpClient
HttpRequestMessage
发送PUT和DELETE请求:
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
public class AdvancedHttpRequestSender
{
private static readonly HttpClient _httpClient = new HttpClient();
public async Task PutExampleAsync(string url, string jsonContent)
{
StringContent content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _httpClient.PutAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"PUT 请求成功,响应内容:\n{responseBody}");
}
public async Task DeleteExampleAsync(string url)
{
HttpResponseMessage response = await _httpClient.DeleteAsync(url);
response.EnsureSuccessStatusCode();
Console.WriteLine($"DELETE 请求成功,状态码: {response.StatusCode}");
}
}携带请求头:
有几种方式可以添加请求头:
全局请求头 (DefaultRequestHeaders
User-Agent
Accept
HttpClient
DefaultRequestHeaders
_httpClient.DefaultRequestHeaders.Add("User-Agent", "MyC#App/1.0");
_httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));针对单个请求的请求头 (HttpRequestMessage
HttpRequestMessage
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/data");
request.Headers.Add("X-Custom-Header", "MyValue");
HttpResponseMessage response = await _httpClient.SendAsync(request);认证信息:
认证通常通过请求头来传递,最常见的是Bearer Token(OAuth 2.0)和Basic Authentication。
Bearer Token: 这是现代API中最常见的认证方式。
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your_access_token_here");
// 或者针对单个请求
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/secure_data");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your_access_token_here");
HttpResponseMessage response = await _httpClient.SendAsync(request);Basic Authentication: 虽然不如Bearer Token安全,但在某些场景下仍在使用。它需要将用户名和密码用冒号连接后进行Base64编码。
string authString = Convert.ToBase64String(Encoding.ASCII.GetBytes("username:password"));
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);网络请求总是充满不确定性,异常处理、超时设置和重试机制是构建健壮客户端的关键。
异常处理:
HttpClient
HttpRequestException
EnsureSuccessStatusCode()
HttpRequestException
StatusCode
try
{
HttpResponseMessage response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode(); // 如果状态码不是2xx,这里会抛出HttpRequestException
// ...
}
catch (HttpRequestException ex)
{
Console.WriteLine($"请求失败: {ex.Message}");
if (ex.StatusCode.HasValue)
{
Console.WriteLine($"HTTP状态码: {ex.StatusCode.Value}");
}
}TaskCanceledException
InnerException
TimeoutException
try
{
// ...
}
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
Console.WriteLine($"请求超时: {ex.Message}");
}
catch (TaskCanceledException ex)
{
Console.WriteLine($"请求被取消: {ex.Message}");
}超时设置:
HttpClient
Timeout
TaskCanceledException
TimeoutException
_httpClient.Timeout = TimeSpan.FromSeconds(10); // 设置10秒超时
这个超时是针对整个请求过程的,包括连接、发送请求和接收响应。对于某些需要长时间处理的请求,你可能需要适当延长这个时间。
重试机制:
对于瞬时性错误(例如网络抖动、服务器短暂过载、429 Too Many Requests),简单的重试通常能解决问题。手动实现重试逻辑会比较繁琐,因为它需要处理延迟、指数退避(每次重试间隔时间逐渐增加)以及最大重试次数等。
在.NET生态系统中,Polly是一个非常流行的弹性策略库,它提供了优雅的方式来实现重试、断路器、超时等多种弹性策略。使用Polly,你可以像这样定义一个重试策略:
// 这是一个概念性的示例,Polly的实际用法会更详细 // using Polly; // using Polly.Extensions.Http; // 定义一个重试策略:重试3次,每次重试间隔时间递增 // var retryPolicy = HttpPolicyExtensions // .HandleTransientHttpError() // 处理瞬时HTTP错误(5xx, 408, DNS等) // .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) // 也可以处理特定状态码 // .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // 然后在发送请求时应用这个策略 // HttpResponseMessage response = await retryPolicy.ExecuteAsync(() => _httpClient.GetAsync(url));
将Polly与
IHttpClientFactory
IHttpClientFactory
HttpClient
以上就是C#的HttpClient类如何发送HTTP请求?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号