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;

代码的实现放在github 和 gitee 欢迎访问

可以通过如下方式获取源代码,先创建一个空文件夹,接着使用命令行 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/284040.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

旧金山参议员提议发布“封杀令”,理由是马路不为机器人所服务

说实话,这个理由有够奇葩。 因为快递无人机所受限制颇多,渐渐地,越来越多的快递机器人被研制出来(这里的“机器人”,包括无人车和及机器人),用于城市的快递发送,比如国内的京东无人…

Socket编程:之双机通信

服务端&#xff1a; 1 #include<sys/socket.h>2 #include<sys/types.h>3 #include<stdio.h>4 #include<unistd.h>5 #include<stdlib.h>6 #include<string.h>7 #include<netdb.h>8 #include<netinet/in.h>9 #include<arpa/i…

jquery中$each()

$.each()&#xff1a;可用于遍历任何的集合(无论是数组或对象) $(selector).each()&#xff1a;专用于jquery对象的遍历, 如果是数组,回调函数每次传入数组的索引和对应的值(值亦可以通过this 关键字获取,但javascript总会包装this 值作为一个对象—尽管是一个字符串或是一个数…

【QGIS入门实战精品教程】7.2:QGIS点状数据符号化设置案例教程

点状符号化的类型有:单一符号、分类、渐进、基于规则、点的位移、点聚类、热图。 相关阅读: 【QGIS入门实战精品教程】7.1:QGIS面状数据符号化设置案例教程 文章目录 一、单一符号二、分类三、渐进四、基于规则五、点的位移六、点聚类七、热图一、单一符号 跟面状符号一样,…

SpringCloud与Dubbo的比较

Dubbo 一、dubbo简介 Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架&#xff0c;使得应用可通过高性能的RPC实现服务的输出和输入功能&#xff0c;可以和Spring框架无缝集成。 Dubbo是一款高性能、轻量级的开源Java RPC框架&#xff0c;它提供了三大核心能力&#xff…

VR 技术加上 8K 画质! 2016 年里约奥运会亮点十足

据报道&#xff0c;2016 年里约奥运会将运用到 VR 技术。 最近&#xff0c;奥林匹克广播服务公司&#xff08;OBS&#xff09;表示出对虚拟现实技术的兴趣&#xff0c;其实用虚拟现实技术报道赛事已经不是什么新鲜的事了&#xff0c;之前 NBA 就这样做过&#xff0c;但是将奥运…

POJ 1986 Distance Queries(LCA)

【题目链接】 http://poj.org/problem?id1986 【题目大意】 给出一棵树&#xff0c;问任意两点间距离。 【题解】 u,v之间距离为dis[u]dis[v]-2*dis[LCA(u,v)] 【代码】 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; c…

WPF 实现柱形统计图

WPF 实现柱形统计图WPF 实现柱形统计图作者&#xff1a;WPFDevelopersOrg原文链接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;项目使用 MIT 开源许可协议&#xff1b;避免画线发虚DrawingContext…

Win11卸载WSL,卸载Windows子系统

虽然 Linux 发行版可以通过 Microsoft Store 安装&#xff0c;但不能通过 Microsoft Store 卸载。 可以通过下列命令卸载。 1、查看当前环境安装的wsl wsl --list2、注销&#xff08;卸载&#xff09;当前安装的Linux的Windows子系统 wsl --unregister Ubuntu3、卸载成功&#…

100亿人口会挨饿吗?人工智能迎击全球粮食问题

给作物看病的AI、走路“长眼”的拖拉机、上帝视角的卫星数据分析——未来吃饭就靠它们了。 图片来源&#xff1a;Blue River Technology 人类又面临了一项危机——随着人口不断膨胀&#xff0c;到2050年人类总人口也许要达到100亿&#xff0c;然而&#xff0c;地球却没有等比例…

Python学习总结15:时间模块datetime time calendar (二)

二 、datetime模块 1. datetime中常量 1&#xff09;datetime.MINYEAR&#xff0c;表示datetime所能表示的最小年份&#xff0c;MINYEAR 1。 2&#xff09;datetime.MAXYEAR&#xff0c;表示datetime所能表示的最大年份&#xff0c;MAXYEAR 9999。 2. datetime中的常见类 da…

switch注意事项

Day03_SHJavaTraining_4-5-2017 switch注意事项&#xff1a;①switch语句接受的数据类型  switch语句中的表达式的数据类型,是有要求的    JDK1.0 - 1.4 数据类型接受 byte short int char    JDK1.5 数据类型接受 byte short int char enum(枚举)  …

WSL1 和 WSL2对比

从 WSL1 更新到 WSL2的主要原因包括&#xff1a; 提高文件系统性能&#xff0c;支持完全的系统调用兼容性。 WSL 2 使用最新、最强大的虚拟化技术在轻量级实用工具虚拟机 (VM) 中运行 Linux 内核。 但是&#xff0c;WSL 2 不是传统的 VM 体验。 ​ 本指南将比较 WSL 1 和 WSL …

SkiaSharp 之 WPF 自绘 粒子花园(案例版)

此案例包含了简单的碰撞检测&#xff0c;圆形碰撞检测方法&#xff0c;也可以说是五环弹球的升级版&#xff0c;具体可以根据例子参考。粒子花园这名字是案例的名字&#xff0c;效果更加具有科技感&#xff0c;很是不错&#xff0c;搞搞做成背景特效也是不错的选择。Wpf 和 Ski…

xshell连接ubuntu

1.更新资料列表 sudo apt-get update2.安装openssh-server sudo apt-get install openssh-server3.查看ssh服务是否启动 sudo ps -e | grep ssh4.如果没有启动&#xff0c;启动ssh服务 sudo service ssh start5.查看IP地址 sudo ifconfig如果出现xshell无法输入密码的情况…

教你从零开始搭建一款前端脚手架工具

本文系原创&#xff0c;转载请附带作者信息&#xff1a;Jrain Lau项目地址&#xff1a;https://github.com/jrainlau/s...前言 在实际的开发过程中&#xff0c;从零开始建立项目的结构是一件让人头疼的事情&#xff0c;所以各种各样的脚手架工具应运而生。笔者使用较多的yoeman…

微信小程序 --- 页面跳转

第一种&#xff1a;wx.navigateTo({}); 跳转&#xff1a; 注意&#xff1a;这种跳转回触发当前页面的 onHide 方法&#xff0c;将当前页面隐藏&#xff0c;然后显示跳转页面。所以可以返回&#xff0c;返回的时候触发 onShow方法进行显示&#xff1a; &#xff08;项目的底部导…

Java基础 深拷贝浅拷贝

Java基础 深拷贝浅拷贝 非基本数据类型 需要new新空间class Student implements Cloneable{private int id;private String name;private Vector course;public Student(){try{Thread.sleep(1000);System.out.println("Student Constructor called.");}catch (Interr…

不安装运行时运行 .NET 程序

好久没写文章了&#xff0c;有些同学问我公众号是不是废了&#xff1f;其实并没有。其实想写的东西很多很多&#xff0c;主要是最近公司比较忙&#xff0c;以及一些其他个人原因没有时间来更新文章。这几天抽空写了一点点东西&#xff0c;证明公众号还活着。长久以来的认知&…

一文弄懂分布式和微服务

简单的说&#xff0c;微服务是架构设计方式&#xff0c;分布式是系统部署方式&#xff0c;两者概念不同。 微服务 简单来说微服务就是很小的服务&#xff0c;小到一个服务只对应一个单一的功能&#xff0c;只做一件事。这个服务可以单独部署运行&#xff0c;服务之间可以通过R…