2011-08-29 95 views
12

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

一些好的信息过的应用程序:HTTP://下载.oracle.com/javase/6/docs/technotes/guides/net/proxies.html –

+0

在sun.net.www.protocol.http.HttpURLConnection中有一个doTunneling()。也许有可能在隧道建立之后拆开那个类并访问下面的套接字......但是你会使用一个可以在任何时候消失的合适的API。如果你使用HttpClient,这不会成为问题。 – prunge

+0

你能弄清楚这一点吗?这是我现在看到的一个问题 – user2202911

回答

0

看起来像你的要求一个SOCKS代理,它不同于HTTP代理。也许尝试Proxy.Type.HTTP。

问题:你的客户端是基于HTTP吗?除非您的客户说出HTTP,否则我不确定这会起作用。

+0

感谢您的提示,我尝试了HTTP,但它不起作用。我的客户端基于HTTP,如果我使用此HTTP代理连接到HTTP服务器,它工作正常 – Johnny

2

你可以试试JHttpTunnel,尽管你需要运行在隧道两端的软件才能工作。

+0

问题是我无法在任何一方安装软件。我看着JHttpTunnel,在Apache或Android中有没有相同的方法? – Johnny

+0

@Johnny如果您无法在两侧安装软件,JHttpTunnel将无法正常工作。如果有帮助,JHttpTunnel基于[GNU HttpTunnel](http://www.nocrew.org/software/httptunnel.html)。 – prunge

1

根据关于HTTP tunneling的维基百科,HTTP代理的重要之处在于它代理了HTTP协议。

所以,如果你有一个服务器和一个客户端,并希望他们通过HTTP代理进行通信,那么服务器和客户端都必须修改以通信HTTP协议。

或者,您需要额外的软件来实现VPN over HTTP,例如OpenVPN。

编辑:一个例外是,一些HTTP代理服务器的支持,并启用一个名为HTTP CONNECT方法,它通过HTTP基本安装过程后允许普通TCP套接字的创建和路由。这允许连接到应用程序,而无需完全转换为HTTP隧道。 MSN Messenger就是一个很好的例子。然而,正如维基百科文章所指出的那样,这个功能经常被禁用,或者出于安全原因甚至不支持。

+0

有没有一个lib可以帮助我以编程方式执行此操作? – Johnny

+0

@Johnny主要的要求是在你可以修改的目标主机旁边有一台服务器。 –

+1

不正确,您可以通过HTTP CONNECT方法隧道传输任何流。 –

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

+0

谢谢Jord。我正在使用URLConnection,但问题是主机服务器只接受Socket连接,而代理服务器只接受HTTP连接。所以我必须通过HTTP代理连接到Socket服务器。 – Johnny

0

我的意思是说你想要的是使用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代理的握手,特别是响应代码将被处理。

0

好了,你可以通过设置请求的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类型代理工作,如果这就是你要设置代理的那种。

2

我创建了一个小的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://stackoverflow.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/

-1

我真的作弄与C++使用通过代理袜子,这个工具帮了我很多,看看这里HERE

+1

请通过一些代码示例 – BillyBigPotatoes

+0

我提供的链接是一个演示开源,相当大的过去... –

相关问题