Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HttpURLConnection使用SOCKS代理而不是HTTP_Java_Windows_Proxy - Fatal编程技术网

Java HttpURLConnection使用SOCKS代理而不是HTTP

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

我有一个非常简单的代码,它使用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,引发以下异常:

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?这是正确的答案(补充了另一个关于覆盖默认代理选择器的答案),但可能需要更多解释。我编辑了答案,以澄清应取消选中“为所有协议使用相同的代理服务器”选项,以便取消选中该选项。