You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework下HttpClient.PostAsync生产环境请求失败求助

.NET Framework中HttpClient.PostAsync连接被远程主机强制关闭问题排查

问题概述

在.NET Framework项目中调用HttpClient.PostAsync请求远程接口时,触发连接被远程主机强制关闭的异常。该功能在开发服务器(IIS部署)正常运行,但生产服务器上无法工作。已尝试修改ServicePointManager.SecurityProtocol添加TLS相关协议,问题仍未解决。

异常栈信息

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
   at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
   at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at CanadianTireDashboard.Controllers.HomeController.<pickUpApi>d__109.MoveNext() in C:\Users\sbaqai\Documents\TFS\CanadianTireDashboard\CanadianTireDashboard\Controllers\HomeController.cs:line 865

核心调用代码

private async Task pickUpApi(string billOfLading)
{
    ErrorFile f = new ErrorFile();

    HomeController hc = new HomeController();
    HttpResponseMessage pickUpRequestCall = null;
    
    //Send a request to url with an xml body
    try
    {
        var url = "https://www.tst-cfexpress.com/xml/pickup";
        
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(pickuprequest));
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        pickuprequest cdn = new pickuprequest();

        var values = cdn.getAll(billOfLading);
        
        try
        {
            var path = $@"C:\CDNTireJobs\Test\{billOfLading}.xml";
            var encoding = Encoding.GetEncoding("ISO-8859-1");
            using (XmlTextWriter tw = new XmlTextWriter(path, encoding))
            {
                xmlSerializer.Serialize(tw, values, ns);
                tw.Close();
            }
        }
        catch (FileNotFoundException e)
        {
            f.errorFile($"File Exception {e.Message}");
        }

     
        var xmlcontent = System.IO.File.ReadAllText($@"C:\CDNTireJobs\Test\{billOfLading}.xml");
        var content = new StringContent(xmlcontent,
                        Encoding.GetEncoding("ISO-8859-1"), "application/xml");

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
        ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

        pickUpRequestCall = await httpClient.PostAsync(url, content);
        f.errorFile(pickUpRequestCall.StatusCode.ToString());
        if (pickUpRequestCall.StatusCode == HttpStatusCode.OK)
        {
            var strResBody = pickUpRequestCall.Content.ReadAsStringAsync().Result;
            f.errorFile(strResBody);
        }
    }
    catch(HttpRequestException e)
    {  
        f.errorFile(e.ToString());
    }
}

排查方向与解决方案

1. 验证生产服务器的TLS协议支持

  • 生产服务器可能存在系统层面的TLS协议限制,可通过PowerShell测试目标接口的兼容性:
    Invoke-WebRequest -Uri "https://www.tst-cfexpress.com/xml/pickup" -UseBasicParsing
    
  • 检查注册表项HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols,确认TLS 1.2的Client端已启用(若目标接口支持,也可尝试启用TLS 1.3)。

2. 排查生产服务器网络环境

  • 测试生产服务器与目标接口的连通性:
    • 用浏览器直接访问目标URL,确认是否能正常加载
    • 用telnet测试443端口:telnet www.tst-cfexpress.com 443
  • 确认生产服务器的防火墙/代理未拦截出站HTTPS请求,目标接口IP已加入出站白名单。

3. 修正HttpClient的使用方式

  • 复用HttpClient实例:将HttpClient声明为类的静态成员,避免每次请求创建新实例(频繁创建会耗尽连接池):
    private static readonly HttpClient httpClient = new HttpClient();
    
  • 移除不必要的HomeController实例创建,避免资源浪费。

4. 调整ServicePointManager设置时机

  • 将ServicePointManager.SecurityProtocol的配置移至应用启动时(如Global.asax的Application_Start方法),因为ServicePoint会被缓存,请求时再设置可能无法生效。

5. 修复证书验证逻辑

  • 生产环境中不要全局禁用证书验证(ServerCertificateValidationCallback返回true),这会带来安全风险。建议将目标接口的SSL证书导入生产服务器的受信任根证书颁发机构。

6. 优化请求内容生成逻辑

  • 避免将XML写入本地文件再读取,直接在内存中序列化生成内容,减少文件IO权限或路径问题:
    string xmlcontent;
    var encoding = Encoding.GetEncoding("ISO-8859-1");
    using (var ms = new MemoryStream())
    {
        xmlSerializer.Serialize(ms, values, ns);
        ms.Position = 0;
        using (var reader = new StreamReader(ms, encoding))
        {
            xmlcontent = reader.ReadToEnd();
        }
    }
    
  • 检查生产服务器上C:\CDNTireJobs\Test路径的读写权限,确保XML文件能正常生成和读取。

内容的提问来源于stack exchange,提问作者Sameed Baqai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:40:37