如何通过HTTP代理连接Socket服务器

我有一段代码连接到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)); 

这篇文章建议我应该使用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.(Socket.java:88) 

你可以试试JHttpTunnel ,虽然你需要在隧道的两边运行软件才能工作。

我创建了小型Socket Factory类来通过套接字处理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/

这是我之前发布的链接:

 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,所以也许这样做?

根据维基百科的HTTP隧道 ,关于HTTP代理的重要事情是它代理HTTP协议。

因此,如果您有服务器和客户端并希望它们通过HTTP代理进行通信,则必须修改服务器和客户端以通信HTTP协议。

或者,您需要可以通过HTTP实现VPN的其他软件,例如OpenVPN。

编辑:一个例外是某些HTTP代理服务器支持并启用了一个名为HTTP CONNECT的方法,该方法在通过HTTP进行基本设置过程后允许创建和路由常规TCP套接字。 这允许连接到应用程序,而无需完全转换为HTTP隧道的艰苦工作。 一个很好的例子是MSN Messenger。 但是,正如维基百科的文章指出,此function经常被禁用,或者甚至出于安全原因甚至不支持。

看起来您正在请求SOCKS代理,这与HTTP代理不同。 也许尝试Proxy.Type.HTTP。

问题:您的客户端是基于HTTP吗? 除非你的客户说HTTP,否则我不确定这是否有效。

我是否正确地说你想要的是使用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代理的所有握手,尤其是响应代码。

那么,您可以通过在代理的URL之后设置请求的URL或使用Java URL来管理代理,如下所示:

 URL u = new URL("http", ProxyHost, ProxyPort, destinationAddress); 

通过使用它,您可以构建一个类似http://ProxyHost:ProxyPorthttp://destinationAddress的URL,这样您就不必在Java中设置可能引发上述exception的Proxy类实例:

 java.lang.IllegalArgumentException: Proxy is null or invalid type at java.net.Socket.(Socket.java:88) 

如果需要管理身份validation设置,则始终可以将身份validation器设置为默认值。

 final String authUser = myAuthUser; final String authPassword = myAuthPassword; Authenticator.setDefault( new Authenticator() { public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication( authUser, authPassword.toCharArray()); } } ); 

即使这是设置代理的一种非常“基本”的方式,但如果这是您必须设置的代理类型,它很可能适用于HTTP类型代理。

我正在使用Socks通过代理编写一个带有c ++的应用程序,这个工具帮了我很多,看看这里