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.pswp.cn/news/284040.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284040.shtml
英文地址,請注明出處:http://en.pswp.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…