如何通过HTTP代理连接Socket服务器
我有一段代码连接到Socket服务器,并且它工作正常。如何通过HTTP代理连接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建议我应该使用雅加达Commons的HttpClient,但如何使用它通过HTTP代理服务器连接套接字服务器?
更新: 我用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)
看起来像你的要求一个SOCKS代理,它不同于HTTP代理。也许尝试Proxy.Type.HTTP。
问题:你的客户端是基于HTTP吗?除非您的客户说出HTTP,否则我不确定这会起作用。
感谢您的提示,我尝试了HTTP,但它不起作用。我的客户端基于HTTP,如果我使用此HTTP代理连接到HTTP服务器,它工作正常 – Johnny
根据关于HTTP tunneling的*,HTTP代理的重要之处在于它代理了HTTP协议。
所以,如果你有一个服务器和一个客户端,并希望他们通过HTTP代理进行通信,那么服务器和客户端都必须修改以通信HTTP协议。
或者,您需要额外的软件来实现VPN over HTTP,例如OpenVPN。
编辑:一个例外是,一些HTTP代理服务器的支持,并启用一个名为HTTP CONNECT方法,它通过HTTP基本安装过程后允许普通TCP套接字的创建和路由。这允许连接到应用程序,而无需完全转换为HTTP隧道。 MSN Messenger就是一个很好的例子。然而,正如*文章所指出的那样,这个功能经常被禁用,或者出于安全原因甚至不支持。
有没有一个lib可以帮助我以编程方式执行此操作? – Johnny
@Johnny主要的要求是在你可以修改的目标主机旁边有一台服务器。 –
不正确,您可以通过HTTP CONNECT方法隧道传输任何流。 –
这是我以前发布的链接:
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,所以也许这样做?
谢谢Jord。我正在使用URLConnection,但问题是主机服务器只接受Socket连接,而代理服务器只接受HTTP连接。所以我必须通过HTTP代理连接到Socket服务器。 – Johnny
我的意思是说你想要的是使用http代理(例如squid)来建立到远程服务器的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代理的握手,特别是响应代码将被处理。
好了,你可以通过设置请求的URL代理服务器的URL之后,或使用Java网址如下管理代理:
URL u = new URL("http", ProxyHost, ProxyPort, destinationAddress);
通过使用这个你构建一个URL像http://ProxyHost:ProxyPorthttp://destinationAddress
让你不在Java中设置了代理类实例,这将有可能抛出异常提到:
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类型代理工作,如果这就是你要设置代理的那种。
我创建了一个小的Socket Factory类来处理通过套接字的HTTP 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://*.com/questions/469695/decode-base64-data-in-java/4265472#4265472
*/
private static class Base64 {
/***********************
* Base64 character set
***********************/
private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"
.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/
一些好的信息过的应用程序:HTTP://下载.oracle.com/javase/6/docs/technotes/guides/net/proxies.html –
在sun.net.www.protocol.http.HttpURLConnection中有一个doTunneling()。也许有可能在隧道建立之后拆开那个类并访问下面的套接字......但是你会使用一个可以在任何时候消失的合适的API。如果你使用HttpClient,这不会成为问题。 – prunge
你能弄清楚这一点吗?这是我现在看到的一个问题 – user2202911