C# 使用StreamReader读取数据时提示连接意外关闭问题求解
问题根因
- 同一
HttpWebRequest实例被重复发起两次请求:ParseHtml方法开头先调用了一次GetResponse获取响应,后续传入WebSiteIsAvailable方法后,修改请求方法为HEAD又调用了一次GetResponse,同一请求实例不可重复发送,直接导致原有连接被强制关闭,触发报错。 - 逻辑顺序错误:站点可用性检查应该在获取响应内容之前执行,原代码先获取响应再做检查,完全失去了检查的意义。
- 资源释放不规范:未使用
using语句自动管理非托管资源,手动调用Close极易出现遗漏,导致连接泄漏、异常断开。 WebSiteIsAvailable方法的response入参完全无效,方法内的using块会直接覆盖该参数值,没有任何复用价值。
修复后代码
using System.Net; using System.IO; using System.Text; // 站点可用性检查方法,独立创建HEAD请求,不与业务请求复用实例 public bool WebSiteIsAvailable(string url) { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Timeout = 15000; request.Method = "HEAD"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { // 仅当响应状态码为200时判定站点可用 return response.StatusCode == HttpStatusCode.OK; } } catch (WebException) { return false; } } public string ParseHtml(string url) { // 先执行可用性检查,不通过直接返回 if (!WebSiteIsAvailable(url)) { return url; } // 检查通过后单独创建GET请求拉取页面内容 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Timeout = 15000; request.Method = "GET"; try { // 用using自动释放响应、流读取器资源,无需手动调用Close using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1251))) { string htmlContent = sr.ReadToEnd(); richTextBox1.Text = htmlContent; return htmlContent; } } catch (WebException) { // 拉取内容过程中出现异常也直接返回原url return url; } }
优化建议
- 避免硬编码编码格式:可以从
response.Headers[HttpResponseHeader.ContentType]中提取站点实际使用的编码,替换硬编码的Encoding.GetEncoding(1251),避免出现乱码问题。 - 可按需配置
request.KeepAlive属性:如果请求的站点不支持长连接,设置request.KeepAlive = false可以减少长连接超时导致的意外断开问题。 - 如果是运行在.NET Core/.NET 5+环境,推荐使用官方更推荐的
HttpClient类替代已过时的HttpWebRequest,性能和稳定性都更优。
内容的提问来源于stack exchange,提问作者Hung PD
相关产品推荐
相关产品推荐

