.Net Core使用HttpClient报“The response ended prematurely”错误如何解决
问题原因分析
- 第一个
响应提前终止报错:你最初使用http协议请求服务端的https监听端口,服务端收到非TLS握手的明文请求后直接断开连接,请求还没到发送业务数据的阶段就失败,因此和你的消息内容完全无关。 - 后续
SSL证书验证失败报错:.NET Core 2.1及以上版本默认使用SocketsHttpHandler处理HttpClient请求,你配置的ServicePointManager.ServerCertificateValidationCallback仅对旧版的WinHttpHandler生效,对默认的Handler不生效,因此跳过证书验证的逻辑没有触发。 - 你原有代码的其他隐性问题:
- 每次调用
callURL都新建HttpClient实例,会导致TCP连接端口耗尽,HttpClient应该设计为单例复用 - 调用
PostAsync.Result同步阻塞异步方法,高概率引发线程死锁 Console.WriteLine("result = " , callURL(url))写法错误,逗号分隔只会将第二个参数作为格式化占位符的值,你没有占位符的情况下不会打印返回的布尔值
- 每次调用
修复方案
本地开发测试(仅测试场景可用,生产环境禁止跳过证书验证)
直接自定义HttpClientHandler配置证书验证回调,同时修复上述隐性问题,修正后代码如下:
namespace HTTPClient { // 要发送的实体对象 public class Msg { public string ID { get; set; } public string Data { get; set; } public int RSSIR { get; set; } public int RSSIT { get; set; } public int Slot { get; set; } } class Program { static Msg msg = new Msg { ID = "00CC", Data = "9F4CC", RSSIR = 123, RSSIT = 321, Slot = 1 }; // 静态复用HttpClient实例,避免端口耗尽 private static readonly HttpClient _httpClient; static Program() { // 自定义Handler跳过证书验证(仅本地测试用) var handler = new HttpClientHandler(); handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; _httpClient = new HttpClient(handler); } // 用异步Main避免同步阻塞 static async Task Main(string[] args) { // 注意改为https协议 string url = "https://127.0.0.1:5001"; bool result = await CallURL(url); Console.WriteLine("result = " + result); Console.ReadKey(); } public static async Task<bool> CallURL(string url) { bool Result = false; _httpClient.BaseAddress = new Uri(url); _httpClient.DefaultRequestHeaders.Accept.Clear(); HttpResponseMessage response = null; try { _httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); HttpContent content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(msg), System.Text.Encoding.UTF8, "application/json"); // 异步等待不要用Result response = await _httpClient.PostAsync("", content); } catch (Exception err) { Console.WriteLine("ERROR"); Console.WriteLine(err); } if (response != null && response.IsSuccessStatusCode) { Result = true; } else { Result = false; } return Result; } } }
生产环境注意事项
生产环境绝对不能跳过证书验证,需要将服务端使用的自签名证书的根证书导入到客户端机器的可信根证书存储区,或者使用CA颁发的可信证书。
内容的提问来源于stack exchange,提问作者Roy Ancri
相关产品推荐
相关产品推荐

