Как я могу указать локальный адрес на java.net.URLConnection?

Мой экземпляр Tomcat прослушивает несколько IP-адресов, но я хочу контролировать, какой IP-адрес источника используется при открытии URLConnection,

Как я могу указать это?

4 ответа

Решение

Это должно сделать трюк:

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

И вы сделали. Не забудьте красиво обработать исключения и, конечно же, изменить значения в соответствии с вашим сценарием.

Ну и я пропустил операторы импорта

Используя Apache HttpClient, я также нашел следующее для работы (для ясности удален try/catch):

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). Будет ли испробован следующий шлюз или он выйдет из строя?

Установка вручную сокета работает нормально...

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

Очевидным переносимым способом было бы установить Proxy в URL.openConnection. Прокси может находиться на локальном хосте, тогда вы можете написать очень простой прокси, который связывает локальный адрес клиентского сокета.

Если вы не можете изменить источник, к которому подключен URL, вы можете заменить URLStreamHandler либо при вызове конструктора URL, либо глобально через URL.setURLStreamHandlerFactory. Затем URLStreamHandler может делегировать обработчику http / https по умолчанию, изменяя вызов openConnection.

Более экстремальным методом будет полная замена обработчика (возможно, расширение реализации в вашем JRE). Кроме того, доступны альтернативные (с открытым исходным кодом) http-клиенты.

Другие вопросы по тегам