循环调用API时请求中断:连接意外关闭问题排查
循环调用API时首次请求成功,后续请求报错:连接意外关闭
我在通过for循环调用API时遇到问题:首次请求(i=1)执行成功,但后续请求均返回错误信息:{"the request was aborted: the connection was closed unexpectedly."}。
以下是我的代码:
for (var i = 1; i <= 4; i++) { var token = GetToken(); string token_cookie = ConfigurationManager.AppSettings["token_cookie"].ToString(); var request = System.Net.WebRequest.Create(url + "/Revenue/GetList") as System.Net.HttpWebRequest; request.Method = "POST"; request.UserAgent = "api-explorer-client"; request.ContentType = "application/json"; request.Headers["Cookie"] = token_cookie; request.Headers["Authorization"] = "Bearer " + token; string body = "{" + "\n " + "\"DateFrom\": \"" + "2024-09-01" + "\"," + "\n " + "\"DateTo\": \"" + DateTime.Now.ToString("yyyy-MM-dd") + "\"," + "\n " + "\"BranchID\": \"" + "0" + "\"," + "\n " + "\"DataType\": \"" + "all" + "\"," + "\n " + "\"PagingNumber\": \"" + 1.ToString() + "" + "\"" + "\n " + "}"; byte[] postBytes = Encoding.UTF8.GetBytes(body); //request.ContentLength = postBytes.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(postBytes, 0, postBytes.Length);//error here } string responseContent = ""; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) { responseContent = streamReader.ReadToEnd(); RevenueList revenueList = JsonConvert.DeserializeObject<RevenueList>(responseContent); DataTable RevList = new DataTable(); RevList = ToDataTable<RevenueListData>(revenueList.Data); InsertBulkTable(RevList, "RevenueList"); //currentPage++; streamReader.Close(); } } request.Abort(); }
我尝试了其他方法,但仍出现该错误。
问题原因及修复方案
1. 恢复ContentLength设置
你注释掉了request.ContentLength = postBytes.Length;,部分服务器要求明确的请求体长度才能正常处理请求,取消注释这行代码:
byte[] postBytes = Encoding.UTF8.GetBytes(body); request.ContentLength = postBytes.Length; // 取消注释此行
2. 调整连接复用相关设置
HttpWebRequest默认复用连接,若服务器端未正确支持Keep-Alive或限制了连接数,会导致后续请求失败。在循环前添加以下配置:
ServicePointManager.Expect100Continue = false; ServicePointManager.DefaultConnectionLimit = 10; // 调高并发连接数限制 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // 指定TLS版本,避免协议兼容问题
3. 优化资源释放与异常捕获
当前代码缺少异常处理,一旦请求出错可能导致资源泄漏。添加try-catch-finally确保资源被正确清理:
for (var i = 1; i <= 4; i++) { HttpWebRequest request = null; try { var token = GetToken(); string token_cookie = ConfigurationManager.AppSettings["token_cookie"].ToString(); request = System.Net.WebRequest.Create(url + "/Revenue/GetList") as System.Net.HttpWebRequest; // ... 其他request配置代码 byte[] postBytes = Encoding.UTF8.GetBytes(body); request.ContentLength = postBytes.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(postBytes, 0, postBytes.Length); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) { responseContent = streamReader.ReadToEnd(); // ... 反序列化与数据插入逻辑 } } } catch (WebException ex) { // 打印错误详情便于排查 Console.WriteLine($"第{i}次请求失败:{ex.Message}"); if (ex.Response != null) { using (StreamReader sr = new StreamReader(ex.Response.GetResponseStream())) { Console.WriteLine("服务器返回错误内容:" + sr.ReadToEnd()); } } } finally { request?.Abort(); } }
4. 改用HttpClient(推荐)
HttpWebRequest是旧版API,HttpClient是.NET官方推荐的HTTP客户端,自带连接池管理,稳定性更强:
// 全局初始化一次HttpClient,不要在循环内重复创建 var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("api-explorer-client"); string token_cookie = ConfigurationManager.AppSettings["token_cookie"].ToString(); httpClient.DefaultRequestHeaders.Add("Cookie", token_cookie); var token = GetToken(); // 若Token有效期覆盖所有请求,可移到循环外 httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); for (var i = 1; i <= 4; i++) { var requestBody = new { DateFrom = "2024-09-01", DateTo = DateTime.Now.ToString("yyyy-MM-dd"), BranchID = "0", DataType = "all", PagingNumber = "1" }; var jsonBody = JsonConvert.SerializeObject(requestBody); var content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { var response = await httpClient.PostAsync(url + "/Revenue/GetList", content); response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync(); // ... 反序列化与数据插入逻辑 } catch (HttpRequestException ex) { Console.WriteLine($"第{i}次请求失败:{ex.Message}"); } }
内容的提问来源于stack exchange,提问作者Tân Nguyễn Đức
相关产品推荐
相关产品推荐

