在Java设置到系统的代理连接
在当今的网络环境中,绝对是企业环境中,应用程序开发人员实际上必须像系统管理员一样经常处理代理。在某些情况下,应用程序应该使用系统默认设置,在其他情况下,对通过哪个代理进行的内容进行非常严格的控制将是附加的,并且在中间的某个地方,大多数应用程序会欣喜若狂地将决定委派给他们为用户提供 GUI 来设置代理设置,就像大多数浏览器一样。
代理服务器充当客户端应用程序和其他服务器之间的接口。在企业环境中,我们经常使用它们来帮助控制用户消费的内容,通常是跨越网络边界。
方法:
我们将找出两种可以在Java跨代理服务器进行连接的方法,如下所示:
- 在 JVM 范围内使用系统属性配置的传统方法。
- 使用 Proxy 类,它通过允许基于每个连接的配置来提供更多控制。
方法 1:使用全局设置
Java展示了一组系统属性,可用于设置 JVM 范围的行为。如果适用于用例,这种“通用”方法通常是最容易实现的。我们可以在调用 JVM 期间从命令行设置所需的属性。或者,我们也可以在运行时使用 System.setProperty() 定义它们。以下是使用命令行定义它们的方法,如下所示:
2.1.通过命令行参数设置
我们可以在命令行中定义代理绕过参数作为系统属性:
java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8080 com.geeksforgeeks.networking.proxies.CommandLineProxyDemo
当以这种方式启动一个进程时,我们可以在 URL 上使用openConnection()而不需要额外的工作:
URL url = new URL(RESOURCE_URL);
URLConnection con = url.openConnection();
2.3使用 System.setProperty() 方法设置代理
如果在使用命令行时出现问题,还有另一种方法可以使用 System.setProperty() 方法来执行此操作。设置代理。
System.setProperty(“http.proxyHost”, “127.0.0.1”);
System.setProperty(“http.proxyPort”, “8080”);
URL url = new URL(RESOURCE_URL);
URLConnection con = url.openConnection();
// …
如果我们随后手动禁用相关的系统属性,则将不再使用代理:
System.setProperty(“http.proxyHost”, null);
现在,这确实存在全局配置的限制,如下所述。
- 全局配置方式是定义代理最简单的方式,但这种方式存在一定的局限性。
- 这种方法提供了在 JVM 范围内的实现,因此为特定协议定义的设置在 JVM 的生命周期内都是有效的,或者直到我们手动取消设置它们。
注意:为了克服这个限制,如果需要,打开和关闭设置可能很有吸引力。但是,有必要确保采取措施防止多线程程序中的并发问题。
因此,作为替代方案,代理 API 更高效,并提供对代理配置的更多控制。作为替代方案,代理 API 提供对代理配置的更精细控制。这催生了另一种通过代理 API 的方法
方法二:使用代理API
Proxy 类为我们提供了一种灵活的方式来在每个连接的基础上配置代理。如果存在任何现有的 JVM 范围代理设置,则使用 Proxy 类的基于连接的代理设置将覆盖它们。以下是我们可以通过 Proxy Type 定义的三种类型的代理:
- HTTP是使用 HTTP 协议的代理
- SOCKS是使用 SOCKS 协议的代理
- DIRECT是一个显式配置的直接连接,没有代理
(A)使用 HTTP 代理
要使用 HTTP 代理,我们首先使用 Proxy 和 Proxy.Type.HTTP 类型包装一个 SocketAddress 实例。接下来,我们只需将 Proxy 实例传递给 URLConnection.openConnection():
URL weburl = new URL(URL_STRING);
Proxy webProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(“127.0.0.1”, 8080));
HttpURLConnection webProxyConnection = (HttpURLConnection) weburl.openConnection(webProxy);
现在,我们将连接到 URL_STRING,然后通过托管在 127.0.0.1:8080 的代理服务器路由该连接。
(B)使用直接代理
我们可能需要直接连接到主机。在这种情况下,我们可以使用静态 Proxy.NO_PROXY 实例显式绕过可以全局配置的代理。在幕后,API 为我们构造了一个新的 Proxy 实例,使用 Proxy.Type.DIRECT 作为类型:
HttpURLConnection directConnection = (HttpURLConnection) weburl.openConnection(Proxy.NO_PROXY);
(C)使用 SOCKS 代理
在处理 URLConnection 时,Socks 代理的工作方式与 HTTP 变体类似。在 Socks 代理中,首先,我们使用 Proxy.Type.SOCKS 类型用代理包装一个 SocketAddress 实例。之后,将 Proxy 实例传递给 URLConnection.openConnection。
Proxy socksProxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(“127.0.0.1”, 1080));
HttpURLConnection socksConnection = (HttpURLConnection) weburl.openConnection(socksProxy);
连接到 TCP 套接字时也可以使用 SOCKS 代理。首先,我们使用 Proxy 实例来构造一个 Socket。之后,我们将目标 SocketAddress 实例传递给 Socket.connect() ,如下所示:
Socket proxySocket = new Socket(socksProxy);
InetSocketAddress socketHost = new InetSocketAddress(SOCKET_SERVER_HOST, SOCKET_SERVER_PORT);
proxySocket.connect(socketHost);
例子:
Java
// Java Program to Create a Simple Proxy Server
// Importing input output classes
import java.io.*;
// Importing
import java.net.*;
public class SimpleProxyServer {
public static void main(String[] args)
throws IOException
{
try {
String host = "your Proxy Server";
int remoteport = 100;
int localport = 111;
// Print a start-up message
System.out.println("Starting proxy for " + host
+ ":" + remoteport
+ " on port " + localport);
// And start running the server
runServer(host, remoteport,
localport); // never returns
}
catch (Exception e) {
System.err.println(e);
}
}
/**
* runs a single-threaded proxy server on
* the specified local port. It never returns.
*/
public static void
runServer(String host, int remoteport, int localport)
throws IOException
{
// Create a ServerSocket to listen for connections
// with
ServerSocket ss = new ServerSocket(localport);
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
final InputStream streamFromClient
= client.getInputStream();
final OutputStream streamToClient
= client.getOutputStream();
// Make a connection to the real server.
// If we cannot connect to the server, send
// an error to the client, disconnect, and
// continue waiting for connections.
try {
server = new Socket(host, remoteport);
}
catch (IOException e) {
PrintWriter out
= new PrintWriter(streamToClient);
out.print(
"Proxy server cannot connect to "
+ host + ":" + remoteport + ":\n"
+ e + "\n");
out.flush();
client.close();
continue;
}
// Get server streams.
final InputStream streamFromServer
= server.getInputStream();
final OutputStream streamToServer
= server.getOutputStream();
// a thread to read the client's requests
// and pass them to the server. A separate
// thread for asynchronous.
Thread t = new Thread() {
public void run()
{
int bytesRead;
try {
while ((bytesRead
= streamFromClient.read(
request))
!= -1) {
streamToServer.write(
request, 0, bytesRead);
streamToServer.flush();
}
}
catch (IOException e) {
}
// the client closed the connection
// to us, so close our connection to
// the server.
try {
streamToServer.close();
}
catch (IOException e) {
}
}
};
// Start the client-to-server request thread
// running
t.start();
// Read the server's responses
// and pass them back to the client.
int bytesRead;
try {
while ((bytesRead
= streamFromServer.read(reply))
!= -1) {
streamToClient.write(reply, 0,
bytesRead);
streamToClient.flush();
}
}
catch (IOException e) {
}
// The server closed its connection to us,
// so we close our connection to our client.
streamToClient.close();
}
catch (IOException e) {
System.err.println(e);
}
finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
}
catch (IOException e) {
}
}
}
}
}
输出:
结论:根据输出,我们了解了如何在核心Java使用代理服务器。首先,我们研究了使用系统属性通过代理服务器进行连接的较旧的、更具全局性的方式。然后,我们看到了如何使用 Proxy 类,它在通过代理服务器连接时提供细粒度的控制。