使用 WinINET 为虚拟用户创建可靠的 HTTP 连接
我正在制作一个程序,在 Windows 上从互联网下载一个简单的文件,使用 Wininet 系列 API,因为我想利用其与 IE 兼容的代理行为。众所周知,当前的 IE 有几种代理设置:自动检测(WPAD)、自动配置(PAC)、手动单个 URL、每个协议的代理服务器、socks、直接...对于大多数用户来说,“直接下载” “ 工作正常;然而,对于某些用户(尤其是那些位于防火墙/NAT后面的用户)来说,他们在建立连接时总是需要特殊的代理设置。
编写代码来处理所有这些情况是很痛苦的,因此我希望带有 InternetOpen (INTERNET_OPEN_TYPE_PRECONFIG)
的 WinINET 可以帮助我。对于大多数用户来说确实如此,但我仍然发现一些用户抱怨连接失败。这些用户可能有非常特殊的网络环境(例如,需要用户名/密码进行代理验证),直接连接对他们不起作用。
有时虚拟用户的配置错误,我希望 wininet 为我尝试“所有”可能的代理设置;不幸的是,INTERNET_OPEN_TYPE_PRECONFIG
只会尝试用户配置的设置,而不是“所有可能的代理设置”。
所以我的问题是,如何制作一个具有最强能力的程序来为虚拟用户(即,他们不明白如何配置他们的系统)解决所有http连接(特别是代理配置)? 是否有任何建议的方法可以建立 HTTP 连接而无需处理代理问题? (即,一个“超级”连接求解器,它将尝试所有可能的代理设置),或者是否有任何方法告诉 WinINET 启用其所有代理设置来创建连接?
I'm making a program which downloads a simple file from internet on Windows, using
Wininet family API because I want to utilize its IE-compatible proxy behavior. As you all know, current IE has several proxy settings: auto-detect (WPAD), auto-configure (PAC), manually single URL, proxy servers per protocol, socks, direct, ... For most users, the "direct download" works fine; however for some users (especially those behind firewall / NAT), they always need special proxy settings when making connections.
It's painful to write code to handle all these cases so I hope WinINET with InternetOpen (INTERNET_OPEN_TYPE_PRECONFIG)
can help me. It does for most users, however I still find some users complaining connection failure. These user may have very special network environments (eg, need username/password auth for proxy) and direct connection does not work for them.
Sometimes dummy users had wrong configuration, and I'd like wininet to try "all" possible proxy settings for me; unfortunately the INTERNET_OPEN_TYPE_PRECONFIG
will only try the one that user configured, not "every possible proxy settings".
So my question is, how do I make a program with most strong ability to workaround all http connection (especially for proxy configuration) for dummy users (i.e, they don't understand how to configure their system)?
Is there any suggested way to make HTTP connections without the need to take care of proxy stuff? (i.e., a "super" connection solver which will try all possible proxy settings), or if there's any method to tell WinINET to enable all its proxy settings to create connection?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一个合理的算法是这样的:
尝试使用用户当前的代理设置(IE 使用的代理设置)进行连接。这些是最有可能发挥作用的。请参阅
WinHttpGetIEProxyConfigForCurrentUser()
在 MSDN 上获取这些设置,或在 WinINet 中获取INTERNET_OPEN_TYPE_PRECONFIG
。如果失败,请尝试直接连接。
如果失败,请尝试使用 WinHttpGetProxyForUrl 进行 WPAD 自动检测。 (WPAD 是客户端可以自动查找网络(通常是公司网络)上的代理自动配置 (PAC) 文件。)您需要选择该选项检查 DHCP 和 DNS 中的代理文件。
WinHTTP 自动代理函数
MSDN 上包含使用此 API 的代码示例和大量支持信息。如果成功,您将获得代理信息,然后可以将其插入 HTTP 下载代码中。 AFAIK,没有等效的 WinINet 选项来自动执行新的 WPAD 检测 - 只有 WinHTTP。接下来您可以尝试查找 Firefox 代理设置。 这个答案 有关这些设置的位置和格式的详细信息,以便您可以通过编程方式访问它们。
如果仍然失败,请要求用户(在您的用户界面中)检查他们的互联网连接是否确实已连接。实际上,用户断开连接比上述所有代理检测步骤失败更为常见。要求用户打开浏览器以确保他们可以访问互联网站点 - 如果上述步骤失败,他们的浏览器可能无法访问网络。用户声明已连接后,请重复步骤 1-3。
如果上述所有方法都失败,您实际上别无选择,只能要求用户手动指定他们的代理信息。您可能想要克隆 IE 或 Firefox 的代理 UI,并将这些 UI 设置转换为适当的参数,以便在下载该文件时配置代理选项。
请注意,代理检测没有什么神奇之处——您的选择是使用用户的设置、使用默认计算机设置、使用直接连接、使用 WPAD 查找 PAC 文件或询问用户。不幸的是,没有办法“在不需要处理代理的情况下建立 HTTP 连接”。
顺便说一句,虽然您可以仅使用 WinHTTP 进行代理检测,然后使用 WinINet 获取文件,但我建议这两个部分都使用 WinHTTP。当您希望对 HTTP 交互实现最大的灵活性和控制(以及比 WinINet 更好的稳定性)时,WinHTTP 是更好的选择。
更新 2:
JJ 上面有一个好主意 - 我添加了一个检查 Firefox 代理设置的步骤。由于奇怪的代理通常出现在企业环境中(通常在 IE 上标准化),因此这不太可能有帮助,但值得一试。
更新:我刚刚编辑了上面的部分,以回应 Francis 的正确评论:严格意义上,WinHTTP 并不是 WinINet 的“继承者”(意味着 WinINet 100% 的功能在 WinHTTP 中可用)。相反,WinHTTP 是为使用 HTTP 进行数据交换且不关心与 Internet Explorer 的缓存、cookie、拨号 UI 等集成的应用程序而设计的。
服务器应用程序肯定属于这一类(WinHTTP 与 WinINet 不同,它是在服务器应用程序中使用是安全的),但许多客户端软件也使用它,例如每台现代 PC 上的 Windows Update 客户端。一般来说,WinHTTP 对于需要通过 HTTP 下载文件、需要对网络进行更细粒度的控制以及想要控制自己的 UI 的客户端应用程序来说是更可取的。
WinHTTP 更实用(例如,您需要进行一个 API 调用来获取代理信息,然后再调用另一个 API 来使用该代理信息),但这种额外的控制程度允许您做一些 WinINet 无法做的事情,例如强制忽略用户的代理设置并尝试新的 WPAD 检测。
A reasonable algorithm would be this:
try a connection using the user's current proxy settings (the ones that IE uses). These are the ones most likley to be working. See
WinHttpGetIEProxyConfigForCurrentUser()
on MSDN to get these settings, orINTERNET_OPEN_TYPE_PRECONFIG
in WinINet.if that fails, try a direct connection.
if that fails, try a WPAD autodetection using WinHttpGetProxyForUrl. (WPAD is the automated way that clients can find a Proxy Auto-Config (PAC) file on a network, typically a corporate network.) You'll want to select the option to check both DHCP and DNS for the proxy file.
WinHTTP AutoProxy Functions
on MSDN contains a code sample using this API and lots of supporting info. If this succeeds, you'll get back the proxy info you can then plug into your HTTP download code. AFAIK, there is not an equivalent WinINet option to do a new WPAD detection automatically-- only WinHTTP.Next you can try to look for Firefox proxy settings. This SO answer details information about the location and format of these settings so you can access them programmatically.
if that still fails, ask the user (in your UI) to check that their internet connection is actually connected. it's actually far more common for users to be disconnected than for all of the above proxy-detection steps to fail. ask the user to open up their browser to make sure they can get to an internet site-- if the steps above fail, their browser is likley unable to see the web. Once the user claims they're connected, repeat steps 1-3.
if all of above fail, the you really have little choice but to ask the user to manually specify their proxy info. You'll probably want to clone the proxy UI of IE or firefox, and turn those UI settings into the appropriate parameters to configure proxy options when you download that file.
Note that there's no magic to proxy detection-- your choices are use the user's settings, use the default computer settings, use a direct connection, use WPAD to find a PAC file, or ask the user. There is, unfortunately, no way to "make HTTP connections without the need to take care of proxy stuff".
BTW, although you could use WinHTTP only for proxy detection and then use WinINet for fetching the file, I'd suggest using WinHTTP for both parts. When you want the most flexibility and control over your HTTP interaction (as well as better stability than WinINet), WinHTTP is preferable.
UPDATE 2:
J.J. had a good idea above-- I added a step for checking Firefox proxy settings. Since oddball proxies are generally found in corporate environments (which tend to standardize on IE) it's somewhat less likley that this will help, but it's worth a try.
UPDATE: I just edited the section above in response to Francis's correct comment: WinHTTP is not the "successor" to WinINet in a strict sense (meaning 100% of the features of WinINet are avilable in WinHTTP). Rather, WinHTTP is designed for apps which are using HTTP for data-interchange and don't care about integrating with Interet Explorer's cache, cookies, dial-up UI, etc.
Server apps definitely fall into this category (WinHTTP, unlike WinINet, is safe for use in server apps) but lots of client software use it too, for example the Windows Update client on every modern PC. In general, WinHTTP is preferable for a client app which needs to download files over HTTP and needs more fine-grained control over the networking and wants to control its own UI.
WinHTTP is more hands-on (for example, you need to make one API call to get proxy info and another to use that proxy info) but that extra degree of control allows you to do things you can't do with WinINet, like forcing ignoring the user's proxy settings and trying a new WPAD detection.
我发现的有关 IE 本身使用的进程的最佳描述位于 Windows Update 客户端如何确定要使用哪个代理服务器用于连接到 Windows Update 网站。将使用 IE 访问 Windows Update 时的顺序与您对 WinINet 或 WinHTTP 的了解相结合 WinHttpGetIEProxyConfigForCurrentUser,WinHttpDetectAutoProxyConfigUrl,WinHttpGetProxyForUrl 和 WinHttpGetDefaultProxyConfiguration 来连接您的应用程序。
以下是知识库文章中的顺序:
The best description I've found of the process IE itself uses is in How the Windows Update client determines which proxy server to use to connect to the Windows Update Web site. Combine the sequence when using IE to access Windows Update with your knowledge of WinINet or WinHTTP WinHttpGetIEProxyConfigForCurrentUser, WinHttpDetectAutoProxyConfigUrl, WinHttpGetProxyForUrl, and WinHttpGetDefaultProxyConfiguration to get your application connected.
Here's the sequence from the KB article: