dotnet 6 为什么网络请求不跟随系统网络代理变化而动态切换代理
本文记录在 dotnet 6 的网络和在 .NET Framework 的行为的变更。在 dotnet 6 下,默认的网络请求在系统网络代理变更的时候,是不会动态切换代理的。例如在应用运行进行网络通讯之后,打开 Fiddler 抓包,此时将会发现 Fiddler 抓不到包,只有在应用重启之后才能抓到。或者是开着 Fiddler 抓包,然后退出 Fiddler 之后应用就断网了
如此行为是因为 Fiddler 抓包其中的一个原理就是设置系统的本机网络代理,而由于 dotnet 6 下,应用不会动态切换代理,如果在应用启动进行网络通讯之后,再打开 Fiddler 抓包,在 Fiddler 打开之后,将会修改系统的本机网络代理,但是 dotnet 6 的应用由于默认不会动态切换代理从而不走 Fiddler 的代理,因此 Fiddler 抓不到包。同理,在开着 Fiddler 抓包之后,退出了 Fiddler 将会修改本机的网络代理,但是由于 dotnet 6 的应用默认不会动态切换代理,在 Fiddler 修改了本机网络代理之后,依然 dotnet 6 的应用还在使用着被关闭的 Fiddler 的网络代理从而断网
核心原因是在 dotnet 6 下变更了网络代理动态切换的行为。其实考古找到这个行为在 .NET Core 2.0 就是默认不支持自动跟随系统代理切换而修改代理
在 .NET Framework 的 4.0 开始,通过监听注册表的 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections 的变更,在变更之后进行刷新网络请求的代理。详细请看 https://referencesource.microsoft.com/#System/net/System/Net/_AutoWebProxyScriptEngine.cs,395

在 .NET Core 下,网络代理的获取只有一次,获取到的代理没有再去监听注册表的变更,也就没有再次刷新。此问题已反馈给官方,详细请看 https://github.com/dotnet/runtime/issues/46910
在 .NET Core 将会在首次获取 HttpClient.DefaultProxy 时进行初始化,值得一提的是在 .NET Core 调用的 WebRequest.GetSystemWebProxy 方法底层也是调用 HttpClient.DefaultProxy 属性
public static IWebProxy GetSystemWebProxy() => HttpClient.DefaultProxy;
以上的 GetSystemWebProxy 实现请看 Make WebRequest.GetSystemWebProxy() return a working proxy by stephentoub · Pull Request #41692 · dotnet/corefx
在 HttpClient.DefaultProxy 里面,将会调用到 SystemProxyInfo.cs 的 ConstructSystemProxy 方法获取对应平台的代理。这个 ConstructSystemProxy 在 OSX 和 Unix 和 Windows 有各自的实现
在 Windows 实现如下
public static IWebProxy ConstructSystemProxy()
{
if (!HttpEnvironmentProxy.TryCreate(out IWebProxy? proxy))
{
HttpWindowsProxy.TryCreate(out proxy);
}
return proxy ?? new HttpNoProxy();
}
在 HttpEnvironmentProxy 里面,将尝试通过环境变量获取代理的配置,也就是说 dotnet 6 应用是支持通过环境变量设置代理,如此更加方便调试。获取的环境变量分别是 ALL_PROXY 和 HTTP_PROXY 和 HTTPS_PROXY 这几个惯例变量
如上面代码,如果获取不到环境变量,那么就进入 HttpWindowsProxy 的代码。在 WinInetProxyHelper 将会读取系统的代理
如上面代码,可以看到,实际上在 HttpClient.DefaultProxy 里面只会获取一次,没有通过注册表的变更再次刷新
这就是网络请求不跟随本机网络代理变化的原因
一个解决方法就是拷贝 dotnet runtime 的读取系统的配置方法,再加上监听注册表变更进行刷新配置,从而实现动态跟随系统代理变化而变化。我拷贝了代码,写了一个版本,使用方法是
var dynamicHttpWindowsProxy = new DynamicHttpWindowsProxy();
HttpClient.DefaultProxy = dynamicHttpWindowsProxy;
可以通过如下方式获取源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 8c64e9676c4205e55fad227a86d5d8d95a5ebe91
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 8c64e9676c4205e55fad227a86d5d8d95a5ebe91
获取代码之后,进入 NilerlanaihikaWhurreeberhalur 文件夹,具体实现放在 Proxy 文件里面,在 Program.cs 包含了测试逻辑,可以不断尝试访问百度。可以测试在使用 HttpClient.DefaultProxy = dynamicHttpWindowsProxy; 时,切换 Fiddler 代理配置,和不使用 DynamicHttpWindowsProxy 切换配置的行为
以上代码基本都是从 dotnet runtime 里面抄的,可以放心用在正式的项目。监听注册表变更是从 https://www.codeproject.com/Articles/4502/RegistryMonitor-a-NET-wrapper-class-for-RegNotifyC 抄的,这是一段比较古老稳定的代码,只不过需要多开启一个线程用来监听注册表。这就是为什么在例子代码里面,会延迟去启动监听注册表
参考文档:
- c# - Default proxy in .net core 2.0 - Stack Overflow
- AutoWebProxyScriptEngine.cs
- Make WebRequest.GetSystemWebProxy() return a working proxy by stephentoub · Pull Request #41692 · dotnet/corefx
- WinHttpWebProxyDataBuilder.cs
- runtime/HttpConnectionPoolManager.cs at 1d9e50cb4735df46d3de0cee5791e97295eaf588 · dotnet/runtime
- HttpClient.DefaultProxy should respect IE proxy changes · Issue #46910 · dotnet/runtime
- how to set default proxy with .NET core 3.1 for HTTP client for any request? - Stack Overflow
- How to change Global Windows Proxy using C# .NET with
Immediate Effect- Stack Overflow - How to auto reset Fiddler when 'system proxy was changed' in Fiddler | Telerik Forums
dotnet 6 为什么网络请求不跟随系统网络代理变化而动态切换代理的更多相关文章
- charles重发网络请求&模拟慢速网络&过滤网络请求
重发网络请求&模拟慢速网络&过滤网络请求 重发网络请求:后端调试的过程中,一直在客户端进行点点点比较麻烦,此时直接发送请求比较方便查看调试后的结果 模拟慢速网络:用户的网络不能一直是快 ...
- 基于Retrofit+RxJava的Android分层网络请求框架
目前已经有不少Android客户端在使用Retrofit+RxJava实现网络请求了,相比于xUtils,Volley等网络访问框架,其具有网络访问效率高(基于OkHttp).内存占用少.代码量小以及 ...
- iOS网络请求基础
这篇是关于网络请求的,结合公司的实际情况编写,如果有不同意见欢迎留言共同讨论. iOS在9.0之后彻底放弃了NSURLConnection,现在已经改用了NSURLSession进行网络请求.一般现在 ...
- # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#
Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...
- swift项目第十天:网络请求工具类的封装
import UIKit /* 必须先导入头文件:import AFNetworking */ import AFNetworking //MARK:-0:定义枚举:以枚举定义请求网络的get和pos ...
- Android网络请求(3) 网络请求框架OkHttp
Android网络请求(3) 网络请求框架OkHttp 本节我们来讲解OkHtpp网络请求框架 什么是网络请求框架 在我的理解中,网络请求框架是为了方便我们更加便捷规范的进行网络请求所建的类,我们通过 ...
- 浅论Android网络请求库——android-async-http
在iOS开发中有大名鼎鼎的ASIHttpRequest库,用来处理网络请求操作,今天要介绍的是一个在Android上同样强大的网络请求库android-async-http,目前非常火的应用Insta ...
- Android网络请求框架
本篇主要介绍一下Android中经常用到的网络请求框架: 客户端网络请求,就是客户端发起网络请求,经过网络框架的特殊处理,让后将请求发送的服务器,服务器根据 请求的参数,返回客户端需要的数据,经过网络 ...
- 网络请求怎么样和UI线程交互? Activity2怎么通知Activity1 更新数据
1.网络请求怎么样和UI线程交互? 目前我的做法是,建立线程池管理网络请求线程,通过添加task来新增网络请求.所有的网络操作通过统一的request来实现,网络返回结果通过回调onError和onS ...
- iOS - ASIHTTPRequest 网络请求
前言 使用 iOS SDK 中的 HTTP 网络请求 API,相当的复杂,调用很繁琐,ASIHTTPRequest 就是一个对 CFNetwork API 进行了封装,并且使用起来非常简单的一套 AP ...
随机推荐
- 二次元 & 动漫壁纸网站(内容记录)
前言 天天和电脑.手机以及平板等电子设备打交道,一个好看的桌面壁纸图片当然是必不可少的,也曾经分享过<值得珍藏的高清壁纸网站推荐>,各种类型和分辨率的壁纸都有. 今天再分享些「高清二次元& ...
- 使用自签名证书在Docker中部署Asp.Net Core(Abp)项目
一 编写Dockerfile文件 FROM mcr.microsoft.com/dotnet/aspnet:6.0 COPY / /app WORKDIR /app EXPOSE 80 ENTRYPO ...
- mybatis @Param参数 记录
报错信息 org.apache.ibatis.binding.BindingException: Parameter 'XX' not found. Available parameters are ...
- 网页实现串口TCP数据通讯的两种方案
概述 串口和TCP数据通讯客户端的形式比较多,但是网页中用的比较少. 其实最大的是网页无法访问本地资源造成的,可能是出于安全方面考虑吧. 解决方案也不是没有,这里介绍几种供大家参考. 方案一:专用 ...
- C++判断操作系统位数
//判断当前系统是否为64位 BOOL Is64BitSystem() { #ifdef _WIN64 return true; #elif _WIN32 HMODULE hModule = Load ...
- 新版本NOI Linux发布,支持VSCode,Code::Blocks开发C++!!!,内附下载地址。
注意VSCODE 虽然有C艹插件,但是在第一次编译的时候必须要有网络,否则用不了 我推荐还是用CODE::BLOCKS 作者10月8日补充 有些省份已经开始强制在NOIP的比赛里使用NOI Linux ...
- keycloak~网站对接到Keycloak的步骤
新网站对接到KC的部署 kc的环境 向kc申请自己的客户端 kc的登录接口 通过code换token接口 刷新token接口 kc的用户信息接口 kc的jwt token说明 1. kc的环境 测试环 ...
- win10上鼠标右键怎么进入cmd
背景: 在win7上有个很好的功能,在文件夹空白区域,按住 " ctrl + 鼠标右键 " 可以直接打开 cmd 窗口 但是在win10上同样的操作方法,打开的窗口却是 power ...
- .NET MAUI开源免费的UI工具包 - Uranium
前言 一直有小伙伴在微信公众号后台留言让我分享一下.NET MAUI相关的UI框架,今天大姚分享一个.NET MAUI开源.免费的UI工具包:Uranium. Uranium介绍 Uranium是一个 ...
- k8s之operator
背景 数字经济的兴起推动了云计算.物联网.大数据行业的快速蓬勃发展,对数据中心提出了更高的要求,同时,用户对于数据库运维自动化的需求越来越高,数据库即服务的需求越来越强烈. 随着k8s的普及以及云原生 ...