Java 如何通过HTTP代理连接套接字服务器
我有一段连接到套接字服务器的代码,它可以正常工作Java 如何通过HTTP代理连接套接字服务器,java,sockets,httpclient,Java,Sockets,Httpclient,我有一段连接到套接字服务器的代码,它可以正常工作 Socket socket = new Socket(); socket.connect(new InetSocketAddress(address, port)); 现在我想通过HTTP代理进行连接,我应该怎么做 我试过了,但失败了 SocketAddress proxyAddr = new InetSocketAddress(proxyHost, proxyPort); Proxy proxy = new Proxy(Proxy.Type.
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));
建议我应该使用Jakarta 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));
它将抛出一个非法的辩论例外
java.lang.IllegalArgumentException: Proxy is null or invalid type
at java.net.Socket.<init>(Socket.java:88)
java.lang.IllegalArgumentException:代理为null或无效类型
位于java.net.Socket(Socket.java:88)
看起来您正在请求SOCKS代理,这与HTTP代理不同。也许可以尝试Proxy.Type.HTTP
问题:您的客户端是基于HTTP的吗?除非您的客户端使用HTTP,否则我不确定这是否有效。您可以尝试,尽管您需要在隧道两侧运行软件才能正常工作。根据Wikipedia on,HTTP代理的重要一点是它代理HTTP协议
因此,如果您有一个服务器和一个客户机,并且希望它们通过HTTP代理进行通信,那么必须修改服务器和客户机,以使用HTTP协议进行通信
或者,您还需要其他软件来实现,例如OpenVPN
Edit:例外情况是,一些HTTP代理服务器支持并启用了一个方法,在HTTP上执行基本设置过程后,该方法允许创建和路由常规TCP套接字。这允许连接到应用程序,而无需进行完全转换为HTTP隧道的艰苦工作。MSN Messenger就是一个很好的例子。然而,正如维基百科文章所指出的,由于安全原因,该功能经常被禁用,甚至不受支持。这是我之前发布的链接:
SocketAddress addr = new InetSocketAddress("webcache.mydomain.com", 8080);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
记住,这个新的代理对象仅代表一个代理定义。我们如何使用这样的对象?URL类中添加了一个新的openConnection()
方法,该方法将代理作为参数,其工作方式与openConnection()
相同,没有参数,只是它强制通过指定的代理建立连接,忽略所有其他设置,包括上述系统属性
完成前面的示例后,我们现在可以添加:
URL url = new URL("http://java.sun.com/");
URLConnection conn = url.openConnection(proxy);
这是我之前发布的链接。我在iPad上,所以无法正确格式化
你能这样做吗?我看到您直接在做套接字,但您在做http,所以可能是这样做的?我说的您想要的是使用http代理(例如squid)建立到远程服务器的连接方法(从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来管理代理,如下所示:
URL u = new URL("http", ProxyHost, ProxyPort, destinationAddress);
通过使用它,您可以构建一个类似http://ProxyHost:ProxyPorthttp://destinationAddress
因此,您不必在Java中设置可能引发上述异常的代理类实例:
java.lang.IllegalArgumentException: Proxy is null or invalid type
at java.net.Socket.<init>(Socket.java:88)
尽管这是设置代理的一种非常“基本”的方法,但如果您必须设置HTTP类型的代理,那么它很可能适用于HTTP类型的代理。我创建了一个小型套接字工厂类来处理通过套接字的HTTP连接。然后,只要代理支持连接到目标,就可以按照正常方式使用套接字
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);
}
}
}
公共最终类SocketFactory{
公共静态套接字GetSocket(字符串主机、字符串端口)引发IOException{
/*************************
*获取jvm参数
*************************/
int-proxyPort=Integer.parseInt(System.getProperty(“http.proxyPort”));
字符串proxyHost=System.getProperty(“http.proxyHost”);
//连接到代理的套接字对象
Socket sock=新套接字(代理主机、代理端口);
/***********************************
*HTTP连接协议RFC2616
***********************************/
字符串proxyConnect=“CONNECT”+主机+:“+端口;
//如果设置了proxyUser和proxyPass,则添加代理授权
试一试{
String proxyUserPass=String.format(“%s:%s”,
System.getProperty(“http.proxyUser”),
System.getProperty(“http.proxyPass”);
concat(“HTTP/1.0\n代理授权:基本”
+Base64.encode(proxyUserPass.getBytes());
}捕获(例外e){
}最后{
proxyConnect.concat(“\n\n”);
}
sock.getOutputStream().write(proxyConnect.getBytes());
/***********************************/
/***************************
*验证HTTP响应。
***************************/
字节[]tmpBuffer=新字节[512];
InputStream socketInput=sock.getInputStream();
int len=socketInput.read(tmpBuffer,0,tmpBuffer.length);
如果(len==0){
抛出新的SocketException(“来自代理的无效响应”);
}
字符串代理响应=新字符串(tmpBuffer,0,len,“UTF-8”);
//应该是HTTP/1.x200,可以吗
if(proxyResponse.indexOf(“200”)!=-1){
//刷新缓冲区中任何未完成的消息
if(socketInput.available()>0)
socketInput.skip(socketInput.available());
//代理连接成功,返回IO的套接字
返回袜子;
}否则{
抛出新的SocketFactoryException(“无法创建套接字”,
促氧化反应);
}
}
/**
*采用GeorgeK最简单的Base64编码器
*
*@见http://stackoverflow.com/questions/469695/decode-base64-data-in-java/4265472#42654
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);
}
}
}
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);
}
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));