C#HttpClient-我可以强制关闭连接吗

本文关键字:连接 我可以 C#HttpClient- | 更新日期: 2023-09-27 18:27:34

我们看到一个问题,即客户点击我们的API并在请求完成之前取消请求。我们认为,他们也正在关闭连接,因此请求不会写入IIS日志。我正试图创建一个跑步者来复制这种行为。我想不通的是如何强制关闭连接,使服务器无法发回数据

这是我当前的代码:

 private static async Task RunMe()
    {
        var cts = new CancellationTokenSource();
        cts.CancelAfter(5000);
        using (var client = new HttpClient())
        {
            try
            {
                client.DefaultRequestHeaders.ConnectionClose = true;
                client.DefaultRequestHeaders.Add("x-apikey", "some key");
                Console.WriteLine("making request");
                using (var response = await client.GetAsync("https://foo.com/api/apitest/testcancel", cts.Token))
                {
                    var result = await response.Content.ReadAsStringAsync();
                    Console.WriteLine($"Request completed: {result}");
                }
            }
            finally
            {                    
                client.CancelPendingRequests();
                Console.WriteLine("about to dispose the client");
                client.Dispose();
            }
        }
    }
}

代码在5秒钟后正确地取消了请求,但在API调用完成后(设置为10秒钟),IIS似乎仍会发回数据。

如何关闭连接,使IIS在我的5s超时后无法发回任何数据?

C#HttpClient-我可以强制关闭连接吗

我终于能够通过使用原始套接字来复制这个问题,这是一项艰巨的工作。让IIS记录取消的请求的方法是在下面的代码中执行以下操作:

  1. 不发送Connection: Close
  2. 不要呼叫Socket.Dispose()

这是最后的工作代码,希望其他人会发现它很有用:

private static void SocketTime(int readTimeout, Random random)
        {
            var ip = IPAddress.Parse("127.0.0.1");
            const int hostPort = 80;
            var hostep = new IPEndPoint(ip, hostPort);
            var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sock.Connect(hostep);
            var uniqueID = random.Next().ToString();
            var get = $"GET http://localhost/api/apitest/testcancel/{uniqueID} HTTP/1.1'r'n" +
                      "x-apikey: somekey'r'n" +
                      "Host: foo.com'r'n" +
                      "Connection: Close'r'n" +
                      "'r'n";

            var getBytes = Encoding.UTF8.GetBytes(get);
            sock.ReceiveTimeout = readTimeout;
            sock.Send(getBytes);
            var responseData = new byte[1024];
            try
            {
                var bytesRead = sock.Receive(responseData);
                var responseString = new StringBuilder();
                while (bytesRead != 0)
                {
                    responseString.Append(Encoding.ASCII.GetChars(responseData), 0, bytesRead);
                    bytesRead = sock.Receive(responseData);
                }
                Console.WriteLine($"SUCCESS => Unique ID = {uniqueID}, Timeout = {readTimeout}");
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode == SocketError.TimedOut)
                {
                    Console.WriteLine($"FAIL => Unique ID = {uniqueID}, Timeout = {readTimeout}");
                }
                else
                {
                    Console.WriteLine("UNHNALDED ERROR: " + e.Message);
                }
            }
            finally
            {
                sock.Dispose();
            }
        }

您可能会受到非常低的超时设置的影响。如果将其设置为足够短的时间,则客户端将关闭连接,尽管服务器仍会尝试返回数据。

如果这不能重现问题,您还可以查看并发性和servicepoint管理器上的属性"UseNagleAlgorithm"。如果此属性为true,则尝试在同一TCP包中对几个小http请求进行打包。它是一个带保护程序的带,但会导致客户端超时,因为操作系统会延迟通过套接字发送数据,直到收集到足够的数据。

是否尝试对响应对象调用Dispose?

查看此帖子:强制关闭与WCF 中HttpClient的连接

相关文章: