2008-09-18 24 views
11

我的Tomcat實例正在偵聽多個IP地址,但我想控制打開URLConnection時使用的是哪個源IP地址。如何在java.net.URLConnection上指定本地地址?

我該如何指定?

+1

如果我的Tomcat是在兩個IP傾聽不同的網關不會忽略(在不同的子網)的代理是如果IP地址,網關我指定會發生什麼暫時不可用,openConnection會拋出一個異常,還是會回落到另一個gateway/ip? – stian 2008-09-18 14:28:00

回答

6

這應該做的伎倆:

URL url = new URL(yourUrlHere); 
Proxy proxy = new Proxy(Proxy.Type.DIRECT, 
    new InetSocketAddress( 
     InetAddress.getByAddress(
      new byte[]{your, ip, interface, here}), yourTcpPortHere)); 
URLConnection conn = url.openConnection(proxy); 

和你做。 不要忘記處理例外很好,當然,改變價值觀,以適應你的情況。

啊,我省略了import語句

+7

這將失敗,並帶*「java.lang.IllegalArgumentException:類型DIRECT與地址my.ip.address.here不兼容*」。潛入代理服務器的源代碼中,我發現只要嘗試輸入* DIRECT,就會拋出此異常。 – user359996 2011-09-09 01:03:24

+0

這不適用於我,我不明白爲什麼。沒有代理就沒問題。通過代理和一個虛擬IP(我的本地主機上的第二個IP地址),我得到一個`ConnectException`。使用套接字而不是`URLConnection`測試也可以正常工作,使用指定了本地地址的4-arg套接字構造函數。是否有其他人請確認他們是否有上述解決方案在本地接口上使用第二個IP? – KomodoDave 2013-05-13 17:00:03

+0

我應該使用哪個本地端口?它不應該由TCP堆棧的較低級別設置,以避免衝突並使端口可重用? – vbence 2013-10-17 13:33:18

1

顯而易見的便攜方式是在URL.openConnection中設置代理。代理可以在本地主機中,然後您可以編寫一個非常簡單的代理來綁定客戶端套接字的本地地址。

如果無法修改URL所連接的源,則可以在調用URL構造函數或全局URL.setURLStreamHandlerFactory時替換URLStreamHandler。然後,URLStreamHandler可以委託給默認的http/https處理程序,修改openConnection調用。

更極端的方法是完全替換處理程序(可能會擴展JRE中的實現)。或者,可選擇(開源)http客戶端。

3

使用Apache Commons的HttpClient我還發現了以下工作(除去試/爲了清晰捕捉):

HostConfiguration hostConfiguration = new HostConfiguration(); 
byte b[] = new byte[4]; 
b[0] = new Integer(192).byteValue(); 
b[1] = new Integer(168).byteValue(); 
b[2] = new Integer(1).byteValue(); 
b[3] = new Integer(11).byteValue(); 

hostConfiguration.setLocalAddress(InetAddress.getByAddress(b)); 

HttpClient client = new HttpClient(); 
client.setHostConfiguration(hostConfiguration); 
GetMethod method = new GetMethod("http://remoteserver/"); 
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
    new DefaultHttpMethodRetryHandler(3, false)); 
int statusCode = client.executeMethod(method); 

if (statusCode != HttpStatus.SC_OK) { 
    System.err.println("Method failed: " + method.getStatusLine()); 
} 

byte[] responseBody = method.getResponseBody(); 
System.out.println(new String(responseBody));"); 

但是,我仍然不知道什麼如果IP的網關關閉(在這種情況下爲192.168.1.11),就會發生。下一個網關會被嘗試還是會失敗?

3

手動設定插座做工精細...

private HttpsURLConnection openConnection(URL src, URL dest, SSLContext sslContext) 
     throws IOException, ProtocolException { 
    HttpsURLConnection connection = (HttpsURLConnection) dest.openConnection(); 
    HttpsHostNameVerifier httpsHostNameVerifier = new HttpsHostNameVerifier(); 
    connection.setHostnameVerifier(httpsHostNameVerifier); 
    connection.setConnectTimeout(CONNECT_TIMEOUT); 
    connection.setReadTimeout(READ_TIMEOUT); 
    connection.setRequestMethod(POST_METHOD); 
    connection.setRequestProperty(CONTENT_TYPE, SoapConstants.CONTENT_TYPE_HEADER); 
    connection.setDoOutput(true); 
    connection.setDoInput(true); 
    connection.setSSLSocketFactory(sslContext.getSocketFactory()); 
    if (src!=null) { 
     InetAddress inetAddress = InetAddress.getByName(src.getHost()); 
     int destPort = dest.getPort(); 
     if (destPort <=0) 
      destPort=SERVER_HTTPS_PORT; 
     int srcPort = src.getPort(); 
     if (srcPort <=0) 
      srcPort=CLIENT_HTTPS_PORT; 
     connectionSocket = connection.getSSLSocketFactory().createSocket(dest.getHost(), destPort, inetAddress, srcPort); 
    } 
    connection.connect(); 
    return connection; 
}