How can I specify the local address on a java.net.URLConnection?

11,710

Solution 1

This should do the trick:

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

And you are done. Dont forget to handle exceptions nicely and off course change the values to suit your scenario.

Ah and I omitted the import statements

Solution 2

Using the Apache commons HttpClient I have also found the following to work (removed try/catch for clarity):

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

However, I still wonder what would happen if the gateway of the IP is down (192.168.1.11 in this case). Will the next gateway be tried or will it fail?

Solution 3

The obvious portable way would be to set a Proxy in URL.openConnection. The proxy can be in local host, you can then write a very simple proxy that binds the local address of the client socket.

If you can't modify the source where the URL is connected, you can replace the URLStreamHandler either when calling the URL constructor or globally through URL.setURLStreamHandlerFactory. The URLStreamHandler can then delegate to the default http/https handler, modifying the openConnection call.

A more extreme method would be to completely replace the handler (perhaps extending the implementation in your JRE). Alternatively, alternative (open source) http clients are available.

Share:
11,710

Related videos on Youtube

stian
Author by

stian

Developer

Updated on April 14, 2022

Comments

  • stian
    stian about 2 years

    My Tomcat instance is listening to multiple IP addresses, but I want to control which source IP address is used when opening a URLConnection.

    How can I specify this?

    • stian
      stian over 15 years
      If my tomcat is listening on two IP adresses with different gateways (on different subnets) what will happen if the gateway for the IP address I specify as proxy is temporarily unavailable, will openConnection throw an exception or will it fall back to the the other gateway/ip?
  • user359996
    user359996 about 13 years
    With the 4.1 codebase (and perhaps earlier?), you can specify the local IP address in a single line: object.getParams().setParameter( "http.route.local-address", ipAddress ), where object is either the HttpClient or the HttpRequest.
  • user359996
    user359996 over 12 years
    This fails with "java.lang.IllegalArgumentException: type DIRECT is not compatible with address my.ip.address.here". Diving into the source for Proxy, I see that this exception will be thrown whenever type DIRECT is attempted.
  • KomodoDave
    KomodoDave almost 11 years
    This doesn't work for me and I can't understand why. Without the proxy it's fine. With the proxy and a virtual IP (second ip address on my localhost) specified I get a ConnectException. Testing with a socket instead of URLConnection also works fine, using the 4-arg socket constructor where local address is specified. Could someone else please confirm if they've got the above solution working with a second IP on local interface?
  • vbence
    vbence over 10 years
    What local port should I use? Isn't it supposed to be set by a lower level of the TCP stack to avoid collisions and make ports reusable?
  • schwarz
    schwarz about 10 years
    Just to make sure I understand this correctly (because I have tested it and it worked), there's only the part where you create a socket that I would like to have some clarifications on. The createSocket() method forces the underlying socket factory to use the socket you've just created ? Because I don't see the connectionSocket variable being used anywhere else. The documentation only mentions "Returns a socket layered over an existing socket connected to the named host, at the given port."
  • pedrofb
    pedrofb over 7 years
    This code can not work. I have reviewed java.net.Proxy since JDK 1.5 and always will throw exception at constructor. See first comment. This answer is not correct