我使用 100% 工作袜,但无法通过我的应用程序进行连接。
SocketAddress proxyAddr = new InetSocketAddress("1.1.1.1", 12345);
Proxy pr = new Proxy(Proxy.Type.SOCKS, proxyAddr);
try
{
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(pr);
con.setConnectTimeout(proxyTimeout * 1000);
con.setReadTimeout(proxyTimeout * 1000);
con.connect();
System.out.println(con.usingProxy());
}
catch(IOException ex)
{
Logger.getLogger(Enter.class.getName()).log(Level.SEVERE, null, ex);
}
那么我做错了什么?如果我将 HTTP 与某些 HTTP 代理一起使用,则一切都可以工作,但不能与 SOCKS 一起使用。
这真的很容易。您只需要设置相关的系统属性,然后继续使用常规的 HttpConnection 即可。
try
{
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(pr);
con.setConnectTimeout(proxyTimeout * 1000);
con.setReadTimeout(proxyTimeout * 1000);
con.connect();
System.out.println(con.usingProxy());
}
catch(IOException ex)
{
Logger.getLogger(Enter.class.getName()).log(Level.SEVERE, null, ex);
}
告知“socksProxyHost”和“socksProxyPort”VM 参数。
例如
System.getProperties().put( "proxySet", "true" );
System.getProperties().put( "socksProxyHost", "127.0.0.1" );
System.getProperties().put( "socksProxyPort", "1234" );
深层来说,HttpClient 是用在 HttpURLConnection 中的。
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
在第 476 行,您可以看到唯一可接受的代理是 HTTP 代理。否则它会直接连接。
奇怪的是,不支持使用 HttpURLConnection 的 SOCKS 代理。更糟糕的是,代码甚至没有使用不受支持的代理,只是忽略代理!
无法解释为什么在该类存在至少 10 年之后没有任何对 SOCKS 代理的支持。
或者这个答案:https://stackoverflow.com/a/64649010/5352325
如果你知道哪些URI需要去代理,你还可以使用底层ProxySelector:https://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html其中for每个建立的 Socket 连接,您可以决定使用哪些代理。
它看起来像这样:
if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
sun.net.www.URLConnection.setProxiedHost(host);
privilegedOpenServer((InetSocketAddress) proxy.address());
usingProxy = true;
return;
} else {
// make direct connection
openServer(host, port);
usingProxy = false;
return;
}
然后使用选择器:
public class MyProxySelector extends ProxySelector {
...
public java.util.List<Proxy> select(URI uri) {
...
if (uri is what I need) {
return list of my Proxies
}
...
}
...
}
您可以传递 JVM 参数来设置将应用于所有 JVM 网络流量的 SOCKS 代理:
public static void main(String[] args) {
MyProxySelector ps = new MyProxySelector(ProxySelector.getDefault());
ProxySelector.setDefault(ps);
// rest of the application
}
更灵活的方法是在运行时使用系统属性来设置它:
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1234 Application
当您需要确保整个应用程序都使用代理时,最好使用通过 JVM 参数或系统属性设置代理。例如,当您需要代理 Spring Boot 应用程序以连接到数据库或类似的东西时。
这是设置代理的最灵活的方式,因为您可以基于每个连接进行设置。以下是使用 Java 11
System.getProperties().put("socksProxyHost", "127.0.0.1");
System.getProperties().put("socksProxyPort", "1234");
和旧版 HttpClient
进行每连接代理的示例:
HttpURLConnection
当您想要隔离特定请求的代理或在运行时动态切换代理时,此方法最有用。您还可以将全局代理与按请求代理混合,这样您就可以设置全局代理,但通过不同的代理发送特定请求。
您可以在此处阅读有关 Java 代理的更多信息:https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html