Java HttpURLConnection使用SOCKS代理而不是HTTP

我有一个非常简单的代码,使用HttpURLConnection通过代理访问一些网站

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,抛出以下exception:

 ERROR: Can't connect to SOCKS proxy:Connection timed out: connect 

如果您在Windows上遇到此问题,则可能会遇到Java错误。

Java将任何系统代理设置视为SOCKS。 您必须禁用useSystemProxies或在Windows中不使用代理。

如果需要代理,请尝试取消选中“对所有协议使用相同的代理服务器”,确保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; } 

也许更好的解决方案是检查注册表并检测正确的设置,但我不想混乱Windows特定的代码(并且所有这些脚本设置也看起来不好)

您需要使用http.proxyHost系统属性。 有关详细信息,请参阅http://java.sun.com/javase/6/docs/technotes/guides/net/proxies.html

 java -Dhttp.proxyHost=webcache.mydomain.com GetURL 

检查某些东西没有设置系统属性中的"socksProxyHost"属性。

编辑

这样描述"useSystemProxies"属性:

“在最近的Windows系统和Gnome 2.x平台上,可以告诉默认的ProxySelector使用系统代理设置(最新版本的Windows和Gnome 2.x可以让你通过用户界面全局设置代理)。系统属性java.net.useSystemProxies被设置为true(为了兼容性,默认情况下它被设置为false),那么默认的ProxySelector将尝试使用这些设置。

所以,假设你没有提供你自己的ProxySelector类,你也应该检查系统代理设置,以确保他们不会说使用SOCKS。