HttpClient 默认无超时,需显式设置Timeout或ConnectTimeout;POST JSON需用JsonContent或StringContent指定application/json;并发需复用HttpClient并调优连接池;HttpRequestException的状态码需根据响应是否返回来判断。

HttpClient 发起请求时连接超时却没报错?
默认情况下 HttpClient 不设超时,底层 TCP 连接可能卡住几十秒甚至更久才失败,表面看是“没响应”,实际是阻塞在连接建立阶段。
- 必须显式设置
Timeout属性,否则依赖操作系统默认(通常 21 秒以上) -
Timeout控制的是整个请求耗时(DNS + 连接 + 发送 + 接收),不是单独的连接超时 - 如需精细控制连接超时,得用
HttpClientHandler配合ServicePointManager或 .NET 6+ 的ConnectTimeout(仅限SocketsHttpHandler) - 示例:
var handler = new SocketsHttpHandler { ConnectTimeout = TimeSpan.FromSeconds(5) };<br>var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(10) };
POST JSON 数据总收到 415 Unsupported Media Type
常见原因是没设 Content-Type,或用了错误的 MIME 类型。.NET 的 JsonContent(.NET 5+)和手动构造 StringContent 行为不同。
- .NET 5 及以上推荐用
JsonContent.Create(obj),它自动设application/json和 UTF-8 BOM-free 编码 - 低版本或需自定义时,用
new StringContent(json, Encoding.UTF8, "application/json"),注意第三个参数不能漏 - 别用
"text/json"或"application/json; charset=utf-8"—— 多数服务不认带charset的写法 - 如果后端是 ASP.NET Core,默认只接受无
charset的application/json
并发调用多个请求时出现 SocketException 或 “Too many open files”
本质是连接池耗尽,HttpClient 实例复用不当 + 默认连接限制太保守导致的。
-
HttpClient必须复用,不要每个请求 new 一个 —— 否则会快速耗尽端口和句柄 - 默认单域名并发连接数上限是 10(.NET Framework)或 100(.NET Core 5+),可通过
SocketsHttpHandler.MaxConnectionsPerServer调整 - 若大量调用不同域名,注意 DNS 解析开销,可考虑启用
EnableMultiplePipelines = true(HTTP/2 场景) - Linux 上还需检查系统级限制:
ulimit -n,必要时调高并配ServicePointManager.DefaultConnectionLimit
捕获 HttpRequestException 却拿不到真实 HTTP 状态码
HttpRequestException 本身不直接暴露 StatusCode,得从内部 InnerException 或响应对象中取,但时机很关键。
- 只有当响应已返回(哪怕 4xx/5xx)且你调用了
response.EnsureSuccessStatusCode()才会抛出含状态码的异常 - 更稳妥的做法是先
await client.SendAsync(request),再判断response.IsSuccessStatusCode,手动处理非 2xx - 若用了
GetAsync/PostAsync等快捷方法,它们内部已调EnsureSuccessStatusCode,此时异常的StatusCode属性可用(.NET Core 3.0+) - 注意:网络层错误(如 DNS 失败、连接拒绝)抛的是不含
StatusCode的HttpRequestException,需靠InnerException类型判断


















