2010-07-04 3 views
2

У меня есть очень простой код, который использует HttpURLConnection для доступа к некоторым веб-сайт через прокси-серверJava HttpURLConnection использует SOCKS прокси вместо HTTP

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 

ответ

5

Если у вас возникли проблемы с Windows, вы можете столкнуться с ошибкой Java.

Java рассматривает любой системный прокси-сервер как SOCKS. Вы должны либо отключить useSystemProxies, либо не использовать прокси-сервер в Windows.

Если требуется прокси-сервер, попробуйте снять флажок «Использовать один и тот же прокси-сервер для всех протоколов», убедившись, что поле для прокси-сервера SOCKS пустое. Это укрепило нашу проблему.

+0

Вот что я подумал. Некоторые люди предложили обходное решение, которое связано с перегрузкой класса DefaultProxySelector, который я собираюсь попробовать. – Demiurg

+0

ZZ Coder, есть ли у вас ссылка на эту «ошибку Java», о которой вы говорили, чтобы я мог найти дополнительную информацию? Откуда вы получили информацию? Была ли эта ошибка подана в Oracle? –

+0

Это правильный ответ (дополняющий другой ответ на переопределение селектора прокси-сервера по умолчанию), но он может использовать больше объяснений. Я отредактировал ответ, чтобы уточнить, что нужно _запустить параметр «Пользователь того же прокси-сервера для всех протоколов», чтобы он не был выбран. –

1

Убедитесь, что что-то не установил "socksProxyHost" свойства в свойствах систем.

EDIT

"useSystemProxies" Свойство описывается следующим образом:

«О новых системах Windows, так и на Gnome 2.x платформах можно сказать, по умолчанию ProxySelector использовать системные настройки прокси-сервера (как последние версии Windows, так и Gnome 2.x позволяют устанавливать прокси-серверы по всему миру через свой пользовательский интерфейс). Если для системного свойства java.net.useSystemProxies установлено значение true (по умолчанию оно равно false для обеспечения совместимости), тогда по умолчанию ProxySelector будет пытаться использовать эти Настройки «.

Таким образом, при условии, что вы не предоставили свой собственный ProxySelector класс, вы должны также проверить системные настройки прокси, чтобы убедиться, что они не говорят, чтобы использовать SOCKS.

+0

Нет , его не задано. – Demiurg

+0

Нет, нет конфигурации SOCKS в настройках прокси-сервера системы. Кроме того, я ожидал бы, что по умолчанию будет использовать HTTP-прокси для HTTP-протокола, или, по крайней мере, позвольте мне установить этот – Demiurg

+0

. Я сдаюсь. Возможно, пришло время запустить ваше приложение с помощью отладчика Java, установить точку останова в 'DefaultProxySelector' и на один шаг. –

1

Вместо этого вам необходимо использовать системное свойство http.proxyHost. См. http://java.sun.com/javase/6/docs/technotes/guides/net/proxies.html.

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

Что случилось с «java.net.useSystemProxies»? В статье, на которую вы ссылаетесь, упоминается об этом. – Demiurg

+1

Любопытно, что настройка proxyHost и proxyPort действительно работает. Еще более любопытно, что ProxySelector.getDefault(). Select (новый URI (urlS)) показывает ту же конфигурацию прокси в обоих случаях. – Demiurg

+0

Есть ли ошибка в java.net.useSystemProxies? – Demiurg

2

Реальная проблема заключается в том, что Java предполагает, что проверка «Использовать тот же прокси-сервер для всех протоколов» также влияет на прокси-сервер SOCKS (я не знаю логики этого диалога в Windows, но это, по крайней мере, запутывает) Если проверка установлена, вы получаете прокси-серверы как для HTTP, так и для SOCKS, что вряд ли будет желательной конфигурацией. Один из способов решить это снятие отметки проверка и выход из поля SOCKS.

Наконец-то я решил создать прокси-фильтр, который сначала вызывает селектор по умолчанию, и если он найдет ту же конфигурацию для соединений 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, определенным кодом (и все эти параметры сценария выглядел плохо, тоже)