我有一段代码连接到Socket服务器,它工作正常。
Socket socket = new Socket();
socket.connect(new InetSocketAddress(address, port));
现在我想通过HTTP代理连接,我该怎么办?
我试过这个并且失败了
SocketAddress proxyAddr = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr);
Socket socket = new Socket(proxy);
socket.connect(new InetSocketAddress(address, port));
this post建议我应该使用 Jakarta Commons HttpClient ,但如何使用它通过HTTP代理连接Socket服务器?
更新: 我使用SOCKS代理,如果我使用HTTP代理它不起作用:
SocketAddress proxyAddr = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
Socket socket = new Socket(proxy);
socket.connect(new InetSocketAddress(address, port));
它将抛出IllegalArgumentException
java.lang.IllegalArgumentException: Proxy is null or invalid type
at java.net.Socket.<init>(Socket.java:88)
答案 0 :(得分:4)
我创建了一个小型Socket Factory类来通过socket处理HTTP CONNECT。然后,如果代理支持CONNECT到目的地,则可以按普通方式使用套接字。
public final class SocketFactory {
public static Socket GetSocket(String host, String port) throws IOException {
/*************************
* Get the jvm arguments
*************************/
int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort"));
String proxyHost = System.getProperty("http.proxyHost");
// Socket object connecting to proxy
Socket sock = new Socket(proxyHost, proxyPort);
/***********************************
* HTTP CONNECT protocol RFC 2616
***********************************/
String proxyConnect = "CONNECT " + host + ":" + port;
// Add Proxy Authorization if proxyUser and proxyPass is set
try {
String proxyUserPass = String.format("%s:%s",
System.getProperty("http.proxyUser"),
System.getProperty("http.proxyPass"));
proxyConnect.concat(" HTTP/1.0\nProxy-Authorization:Basic "
+ Base64.encode(proxyUserPass.getBytes()));
} catch (Exception e) {
} finally {
proxyConnect.concat("\n\n");
}
sock.getOutputStream().write(proxyConnect.getBytes());
/***********************************/
/***************************
* validate HTTP response.
***************************/
byte[] tmpBuffer = new byte[512];
InputStream socketInput = sock.getInputStream();
int len = socketInput.read(tmpBuffer, 0, tmpBuffer.length);
if (len == 0) {
throw new SocketException("Invalid response from proxy");
}
String proxyResponse = new String(tmpBuffer, 0, len, "UTF-8");
// Expecting HTTP/1.x 200 OK
if (proxyResponse.indexOf("200") != -1) {
// Flush any outstanding message in buffer
if (socketInput.available() > 0)
socketInput.skip(socketInput.available());
// Proxy Connect Successful, return the socket for IO
return sock;
} else {
throw new SocketFactoryException("Fail to create Socket",
proxyResponse);
}
}
/**
* Simplest Base64 Encoder adopted from GeorgeK
*
* @see http://stackoverflow.com/questions/469695/decode-base64-data-in-java/4265472#4265472
*/
private static class Base64 {
/***********************
* Base64 character set
***********************/
private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
.toCharArray();
/**
* Translates the specified byte array into Base64 string.
*
* @param buf
* the byte array (not null)
* @return the translated Base64 string (not null)
*/
public static String encode(byte[] buf) {
int size = buf.length;
char[] ar = new char[((size + 2) / 3) * 4];
int a = 0;
int i = 0;
while (i < size) {
byte b0 = buf[i++];
byte b1 = (i < size) ? buf[i++] : 0;
byte b2 = (i < size) ? buf[i++] : 0;
int mask = 0x3F;
ar[a++] = ALPHABET[(b0 >> 2) & mask];
ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask];
ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask];
ar[a++] = ALPHABET[b2 & mask];
}
switch (size % 3) {
case 1:
ar[--a] = '=';
case 2:
ar[--a] = '=';
}
return new String(ar);
}
}
}
https://code.google.com/p/java-socket-over-http-proxy-connect/
答案 1 :(得分:2)
您可以尝试JHttpTunnel,但您需要在隧道两侧运行软件才能实现此目的。
答案 2 :(得分:2)
这是我之前发布的链接:
SocketAddress addr = new InetSocketAddress("webcache.mydomain.com", 8080);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
请记住,这个新的代理对象代表了一个代理定义,仅此而已。我们如何使用这样的对象?新的openConnection()
方法已添加到URL类中,并将Proxy作为参数,它的工作方式与openConnection()
的方式相同,不带参数,但强制通过指定的代理建立连接,忽略所有其他设置,包括上面提到的系统属性。
完成上一个示例后,我们现在可以添加:
URL url = new URL("http://java.sun.com/");
URLConnection conn = url.openConnection(proxy);
这是我之前发布的链接。我在iPad上,所以无法正确格式化。
你能这样做吗?我看到你正在直接进行套接字,但你正在做http,所以也许这样做?
答案 3 :(得分:0)
看起来您正在请求SOCKS代理,该代理与HTTP代理不同。也许尝试Proxy.Type.HTTP。
问题:您的客户端是基于HTTP吗?除非你的客户说HTTP,否则我不确定这是否有效。
答案 4 :(得分:0)
根据维基百科HTTP tunneling,关于HTTP代理的重要之处在于它代理了HTTP协议。
因此,如果您有服务器和客户端并希望它们通过HTTP代理进行通信,则必须修改服务器和客户端以通信HTTP协议。
或者,您需要其他可以实现VPN over HTTP的软件,例如OpenVPN。
编辑:一个例外是某些HTTP代理服务器支持并启用了一个名为HTTP CONNECT的方法,该方法通过HTTP进行基本设置过程后,允许创建和路由常规TCP套接字。这允许连接到应用程序,而无需完全转换为HTTP隧道的艰苦工作。一个很好的例子就是MSN Messenger。但是,正如维基百科的文章所述,这个功能经常被禁用,或者出于安全原因甚至不支持。
答案 5 :(得分:0)
我是否正确地说你想要的是使用http代理(例如鱿鱼)来建立到远程服务器的CONNECT方法(来自http rfc 2616)?基本上,连接是这样的:
-open a socket to the proxy (host, port)
-send text to the proxy with basic header
....CONNECT remote.internethost.com:1494 HTTP/1.0
....User-Agent: Java Proxy Socket version 1.0a
....Host: remote.internethost.com
....Proxy-Authorization: Basic YourBase64usernamePasswordIfRequired
-then, the proxy will return a http status code (multiline text string) and the actual socket (if successfull)
-this is this socket that needs to be returned to the connection object
这可以通过个人课程完成,但美妙的是重用代理类。这样,所有与http代理的握手,特别是响应代码都将被处理。
答案 6 :(得分:0)
嗯,您可以通过在代理的网址后面设置请求的网址,或者使用Java网址来管理代理:
URL u = new URL("http", ProxyHost, ProxyPort, destinationAddress);
通过使用它,您可以构建一个类似http://ProxyHost:ProxyPorthttp://destinationAddress
的URL,这样您就不必在Java中设置可能引发上述异常的Proxy类实例:
java.lang.IllegalArgumentException: Proxy is null or invalid type
at java.net.Socket.<init>(Socket.java:88)
如果您需要管理身份验证设置,您始终可以将身份验证器设置为默认设置。
final String authUser = myAuthUser;
final String authPassword = myAuthPassword;
Authenticator.setDefault(
new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
authUser, authPassword.toCharArray());
}
}
);
即使这是设置代理的一种非常“基本”的方式,如果这是您必须设置的代理类型,它很可能适用于HTTP类型代理。
答案 7 :(得分:0)
我看到一个很老的帖子,不知道有没有人在找这个。对我来说,打击片段工作得很好。
Socket socketProxy = null;
if(System.getProperty("http.proxyHost") != null) {
if(System.getProperty("http.proxyUser") != null) {
String proxyUser = System.getProperty("http.proxyUser");
String proxyPassword = System.getProperty("http.proxyPassword");
//For Proxy Authentication
Authenticator.setDefault( new Authenticator() {
@Override public PasswordAuthentication getPasswordAuthentication() { return
new PasswordAuthentication(proxyUser, proxyPassword.toCharArray()); } } );
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); // By default basic auth is disabled, by this basic auth is enabled
}
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(System.getProperty("http.proxyHost"), Integer.parseInt(System.getProperty("http.proxyPort"))));
socketProxy = new Socket(proxy);
InetSocketAddress address = InetSocketAddress.createUnresolved(host, port); // create a socket without resolving the target host to IP
socketProxy.connect(address);
}
我从原始帖子中注意到的一件事是没有使用 proxyAddr。不知道是这篇文章中的错别字还是错误。
SocketAddress **proxyAddr** = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Proxy.Type.HTTP, **addr**);
Socket socket = new Socket(proxy);
socket.connect(new InetSocketAddress(address, port));
答案 8 :(得分:-1)
我正在使用Socks通过代理编写一个带有c ++的应用程序,这个工具帮了我很多忙,看看HERE