2008-09-18 26 views
11

Ví dụ Tomcat của tôi đang nghe nhiều địa chỉ IP, nhưng tôi muốn kiểm soát địa chỉ IP nguồn được sử dụng khi mở một URLConnection.Làm cách nào để chỉ định địa chỉ cục bộ trên java.net.URLConnection?

Tôi làm cách nào để xác định điều này?

+1

Nếu tomcat tôi đang lắng nghe trên hai địa chỉ IP cho các cổng với nhau (trên mạng con khác nhau) những gì sẽ xảy ra nếu là cửa ngõ cho các địa chỉ IP tôi chỉ định như proxy là tạm thời không có sẵn, sẽ openConnection ném một ngoại lệ hoặc nó sẽ rơi trở lại cửa ngõ khác/ip? – stian

Trả lời

6

này nên làm như lừa:

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); 

Và bạn đã làm xong. Đừng quên xử lý các ngoại lệ độc đáo và tắt khóa học thay đổi các giá trị cho phù hợp với kịch bản của bạn.

Ah và tôi bỏ qua những điều khoản về nhập khẩu

+7

Điều này không thành công với * "java.lang.IllegalArgumentException: loại DIRECT không tương thích với địa chỉ my.ip.address.here" *. Lặn vào nguồn cho Proxy, tôi thấy rằng ngoại lệ này sẽ được ném * bất cứ khi nào * loại DIRECT được thử. – user359996

+0

Điều này không hiệu quả đối với tôi và tôi không thể hiểu tại sao. Nếu không có proxy thì tốt. Với proxy và một IP ảo (địa chỉ IP thứ hai trên localhost của tôi), tôi đã chỉ định một 'ConnectException'. Thử nghiệm với một socket thay vì 'URLConnection' cũng hoạt động tốt, bằng cách sử dụng hàm tạo socket 4-arg nơi địa chỉ cục bộ được chỉ định. Ai đó có thể vui lòng xác nhận nếu họ đã có giải pháp trên làm việc với IP thứ hai trên giao diện cục bộ? – KomodoDave

+0

Tôi nên sử dụng cổng địa phương nào? Không phải là nó phải được thiết lập bởi một mức thấp hơn của ngăn xếp TCP để tránh va chạm và làm cho cổng tái sử dụng? – vbence

1

Cách di động rõ ràng sẽ là đặt Proxy trong URL.openConnection. Proxy có thể là máy chủ cục bộ, sau đó bạn có thể viết một proxy rất đơn giản gắn kết địa chỉ cục bộ của ổ cắm máy khách.

Nếu bạn không thể sửa đổi nguồn nơi URL được kết nối, bạn có thể thay thế URLStreamHandler khi gọi đến hàm tạo URL hoặc trên toàn cầu thông qua URL.setURLStreamHandlerFactory. Sau đó, URLStreamHandler có thể ủy quyền cho trình xử lý http/https mặc định, sửa đổi cuộc gọi openConnection.

Một phương pháp cực đoan hơn là thay thế hoàn toàn trình xử lý (có thể mở rộng việc triển khai trong JRE của bạn). Ngoài ra, khách hàng http thay thế (nguồn mở) có sẵn.

3

Sử dụng commons Apache HttpClient Tôi cũng đã tìm thấy những điều sau đây để làm việc (loại bỏ try/catch cho rõ ràng):

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));"); 

Tuy nhiên, tôi vẫn tự hỏi điều gì sẽ xảy ra nếu cổng IP bị hỏng (192.168.1.11 trong trường hợp này). Cổng tiếp theo sẽ được thử hay nó sẽ thất bại?

+1

Với 4.1 codebase (và có lẽ sớm hơn?), Bạn có thể chỉ định địa chỉ IP cục bộ trong một dòng: ** object.getParams(). SetParameter ("http.route.local-address", ipAddress) **, trong đó ** đối tượng ** là ** HttpClient ** hoặc ** HttpRequest **. – user359996

3

Thiết tự ổ cắm làm việc tốt ...

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; 
}  
+0

Chỉ để chắc chắn rằng tôi hiểu điều này một cách chính xác (bởi vì tôi đã thử nghiệm nó và nó đã hoạt động), chỉ có một phần nơi bạn tạo một ổ cắm mà tôi muốn có một số giải thích.Phương thức createSocket() buộc nhà máy socket bên dưới sử dụng socket bạn vừa tạo ra? Bởi vì tôi không thấy biến connectionSocket đang được sử dụng ở bất kỳ nơi nào khác. Tài liệu chỉ đề cập đến "Trả về một ổ cắm được xếp chồng lên một ổ cắm hiện có được kết nối với máy chủ có tên, tại cổng đã cho." – schwarz

Các vấn đề liên quan