Java HttpURLConnection使用SOCKS代理而不是HTTP
我有一个非常简单的代码,它使用HttpURLConnection通过代理访问一些网站Java HttpURLConnection使用SOCKS代理而不是HTTP,java,windows,proxy,Java,Windows,Proxy,我有一个非常简单的代码,它使用HttpURLConnection通过代理访问一些网站 System.setProperty("java.net.useSystemProxies", "true"); System.out.println("Proxy: " + ProxySelector.getDefault().select(new URI(urlS))); URL url = new URL(urlS); HttpURLConnection ic = (Htt
System.setProperty("java.net.useSystemProxies", "true");
System.out.println("Proxy: " + ProxySelector.getDefault().select(new URI(urlS)));
URL url = new URL(urlS);
HttpURLConnection ic = (HttpURLConnection)url.openConnection();
ic.connect();
出于某种原因,Java认为我需要SOCKS代理,而不是http,引发以下异常:
ERROR: Can't connect to SOCKS proxy:Connection timed out: connect
检查系统属性中是否未设置
“socksProxyHost”
属性
编辑
“useSystemProxies”
属性描述如下:
“在最新的Windows系统和Gnome 2.x平台上,可以告诉默认的ProxySelector
使用系统代理设置(Windows和Gnome 2.x的最新版本都允许您通过其用户界面全局设置代理)。如果系统属性java.net.useSystemProxies
设置为true(出于兼容性考虑,默认设置为false),然后默认的ProxySelector
将尝试使用这些设置。”
因此,假设您没有提供自己的
ProxySelector
类,您还应该检查系统代理设置,以确保它们没有说要使用SOCKS。您需要使用http.proxyHost
系统属性。有关详细信息,请参阅
java -Dhttp.proxyHost=webcache.mydomain.com GetURL
如果您在Windows上遇到此问题,您可能会遇到Java错误 Java将任何系统代理设置视为SOCKS。您必须在Windows中禁用UseSystemProxy或不使用代理
如果需要代理,请尝试取消选中“对所有协议使用相同的代理服务器”,确保SOCKS代理的字段为空。这解决了我们的问题。真正的问题是Java假设“对所有协议使用相同的代理服务器”检查也会影响SOCKS代理(我不知道Windows中此对话框背后的逻辑,但至少令人困惑) 如果设置了该检查,您将为HTTP和SOCKS启用代理,这很可能不是所需的配置。 解决此问题的一种方法是取消选中复选框并将SOCKS字段留空 我最终解决了这个问题,创建了一个ProxySelector,它首先调用默认选择器,如果它为HTTP和SOCKS连接找到相同的配置,它会忽略SOCKS代理
public class SocksFixerProxySelector extends ProxySelector {
ProxySelector base;
public SocksFixerProxySelector() {
base = ProxySelector.getDefault();
}
@Override
public List<Proxy> select(URI uri) {
List<Proxy> baseList = base.select(uri);
try {
if (uri.getScheme().equals("socket")) {
Proxy socksProxy = findByType(baseList, Type.SOCKS);
if (socksProxy != null) {
URI httpTestUri = new URI("http", uri.getHost(), uri.getPath(), uri.getFragment());
Proxy httpProxy = findByType(base.select(httpTestUri), Type.HTTP);
if (httpProxy != null && socksProxy.address().equals(httpProxy.address())) {
// Quitamos SOCKS
List<Proxy> filteredList = new ArrayList<>(baseList);
filteredList.remove(socksProxy);
return filteredList;
}
}
}
} catch (Exception e) {
}
return baseList;
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
base.connectFailed(uri, sa, ioe);
}
private Proxy findByType(List<Proxy> proxies, Proxy.Type type) {
for (Proxy proxy : proxies) {
if (proxy.type() == type)
return proxy;
}
return null;
}
公共类SocksFixerProxySelector扩展ProxySelector{
ProxySelector碱基;
公用插座FixerProxy选择器(){
base=ProxySelector.getDefault();
}
@凌驾
公共列表选择(URI){
List baseList=base.select(uri);
试一试{
if(uri.getScheme().equals(“套接字”)){
代理socksProxy=findByType(baseList,Type.SOCKS);
if(socksProxy!=null){
URI httpTestUri=新URI(“http”,URI.getHost(),URI.getPath(),URI.getFragment());
Proxy-httpProxy=findByType(base.select(httpTestUri),Type.HTTP);
if(httpProxy!=null&&socksProxy.address().equals(httpProxy.address())){
//基塔莫斯袜子
List filteredList=新的ArrayList(基本列表);
过滤器列表。移除(socksProxy);
返回过滤器列表;
}
}
}
}捕获(例外e){
}
返回基本列表;
}
@凌驾
public void connectFailed(URI、SocketAddress sa、IOException ioe){
connectFailed(uri、sa、ioe);
}
专用代理findByType(列出代理,Proxy.Type){
for(代理:代理){
if(proxy.type()==type)
返回代理;
}
返回null;
}
也许更好的解决方案是检查注册表并检测正确的设置,但我不想弄乱Windows特定的代码(所有这些脚本设置看起来也很糟糕)java.net.useSystemProxies有什么问题?您引用的文章也提到了它。奇怪的是,设置proxyHost和proxyPort确实有效。更奇怪的是,设置ProxySelector.getDefault().select(新URI(URL))在这两种情况下都显示相同的代理配置。java.net.useSystemProxies中是否存在错误?我不知道。我们的主要生产平台不提供系统代理配置。不,系统代理设置中没有SOCKS配置。此外,我预计默认情况下,它将使用HTTP proxy作为HTTP协议,或者至少I don’我不允许设置它,我放弃了。也许是时候使用Java调试器运行应用程序了,在
DefaultProxySelector
中设置一个断点,然后单步执行。在我看来,JDK中有一个bug。发现了其他一些[未解决]关于这个问题的报告这就是我所想的。一些人建议了一种解决方法,包括重载DefaultProxySelector类,我将尝试使用它。ZZ Coder,你有关于这个“Java bug”的参考资料吗您所说的是为了让我可以找到更多信息?您从哪里获得信息?此错误是否已提交给Oracle?这是正确的答案(补充了另一个关于覆盖默认代理选择器的答案),但可能需要更多解释。我编辑了答案,以澄清应取消选中“为所有协议使用相同的代理服务器”选项,以便取消选中该选项。