2

I have a pool of public ip addresses configured on my multiple NICs. In my JAVA project, which runs on a LINUX machine, I need to select a specific ip address from the pool and create an HttpURLConnecion using that ip. Further, I will cycle on the pool, using each time a different ip.

At the current stage, I was not able to find a solution using the java.net library. I have rather looked at the HttpClient from Apache. At the following link, http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html, it is said that such library can support the functionality I was looking for. A discussion on this can be found at Define source ip address using Apache HttpClient. Actually, the posted thread seems not conclusive, as users' experiences are very contrasting on the described use of the library.

Therefore, I don't think that SO community really succeeded in solving this issue. It is a matter of fact that several replayed questions/answers on this topic can be found on SO, but none of them seems to give an exhaustive analysis of the problem.

Moreover, the problem is not faced with the use of java.net library (as in my project) at all.

At the moment, a possible option that I have is to invoke some LINUX system commands (from java) to switch the NIC to use for the current connection. However, I have not figure it out yet.

Therefore, I would appreciate if any users, who had POSITIVE experiences in solving this issue, can address me to a solution/idea/method.

Thanks in advance,

Marcello

UPDATE:

I've currently implemented this test code. It gives me correct status code (200). However, it needs to be tested with multiple ip addresses.

public class test {

    public static void main(String[] args) {

        final String authUser = "admin";
        final String authPassword = "password";
        Authenticator.setDefault(
           new Authenticator() {
              public PasswordAuthentication getPasswordAuthentication() {
                 return new PasswordAuthentication(
                       authUser, authPassword.toCharArray());
              }
           }
        );

        System.setProperty("http.proxyUser", authUser);
        System.setProperty("http.proxyPassword", authPassword);

        try {

            Properties systemProperties = System.getProperties();
            URL url = new URL("yourURL");
            systemProperties.setProperty("http.proxyHost","localhost");
            systemProperties.setProperty("http.proxyPort", "8080");                         

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            int status = connection.getResponseCode();
            System.out.println(status);

        } catch (IOException e) {
            System.out.println("connection problems");
        }
    }

}

At this point, you should be able to configure the different TCP ports related to each NIC. Did anyone try something like this? I am looking forward to reading new ideas/comments.

UPDATE 2: To be precise, I've included authentication setup for those who needed it.

4

4 回答 4

3

为什么不直接使用 org.apache.httpcomponents?

这是一个有效的示例(使用 maven 插件 org.apache.httpcomponents,版本 4.3.1):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class HttpClientExample {

    public void gogo() throws ClientProtocolException, IOException {

        CloseableHttpClient httpclient = HttpClients.createDefault();

        // Local interface1:
        byte ip1[] = new byte[] { (byte)192, (byte)168, (byte)100, (byte)32 };
        // Local interface2:
        byte ip2[] = new byte[] { (byte)192, (byte)168, (byte)100, (byte)33 };


        RequestConfig requestConfig = RequestConfig.custom().setLocalAddress(InetAddress.getByAddress(ip1)).build();
        try {
            HttpGet httpget = new HttpGet("http://server.com");
            httpget.setConfig(requestConfig);
            System.out.println("executing request" + httpget.getRequestLine());
            StringBuilder response = httpclient.execute(httpget,handler);
            System.out.println(response.toString());

            requestConfig = RequestConfig.custom().setLocalAddress(InetAddress.getByAddress(ip2)).build();
            httpget = new HttpGet("http://server.com");
            httpget.setConfig(requestConfig);
            System.out.println("executing request" + httpget.getRequestLine());
            response = httpclient.execute(httpget,handler);
            System.out.println(response.toString());
        } finally {
            httpclient.close();
        }
    }

    private final ResponseHandler<StringBuilder> handler = new ResponseHandler<StringBuilder>() {
        @Override
        public StringBuilder handleResponse(final HttpResponse response)
                throws ClientProtocolException, IOException {
            return sortResponse(response);
        }
    };

    private StringBuilder sortResponse(final HttpResponse httpResponse) throws IOException {
        StringBuilder builder = null;

        if (httpResponse != null) {
            switch (httpResponse.getStatusLine().getStatusCode()) {
                case HttpStatus.SC_OK:
                    final HttpEntity entity = httpResponse.getEntity();
                    if (entity != null) {

                        final InputStreamReader instream = new InputStreamReader(entity.getContent());
                        try {
                            final BufferedReader reader = new BufferedReader(instream);
                            builder = new StringBuilder();
                            String currentLine = null;
                            currentLine = reader.readLine();
                            while (currentLine != null) {
                                builder.append(currentLine).append("\n");
                                currentLine = reader.readLine();
                            }
                        } finally {
                            instream.close();
                        }
                    }
                    break;
                default:
                    throw new IllegalArgumentException("Error.");
            }
        }
        return builder;
    }
}
于 2013-10-22T18:55:13.967 回答
0

java.net使用sun.net.www.protocol包创建HttpURLConnection.

sun.net.www.protocol.HttpURLConnectionjava.net.HttpURLConnection接口的实现。

尝试从包中扩展sun.net.www.protocol.HttpURLConnection和其他适当的类,例如NetworkClientHttpClient协议处理程序类sun.www.

于 2013-10-22T12:40:32.893 回答
0

使用 linux 命令“ip addr”,其输出类似于:

[root@user ~]# ip 地址

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:18:a5:97 brd ff:ff:ff:ff:ff:ff
    inet 100.10.52.15/24 brd 10.0.2.255 scope global eth1
    inet 100.10.52.16/24 brd 10.0.2.255 scope global secondary eth1
    inet6 fe80::a00:27ff:fe18:a597/64 scope link
       valid_lft forever preferred_lft forever
3: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:11:1f:0c brd ff:ff:ff:ff:ff:ff
    inet 158.17.47.19/24 brd 172.17.37.255 scope global eth2
    inet6 fe80::a00:27ff:fe11:1f0c/64 scope link
       valid_lft forever preferred_lft forever
4: eth3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:cf:96:2d brd ff:ff:ff:ff:ff:ff
    inet6 fe80::a00:27ff:fecf:962d/64 scope link
       valid_lft forever preferred_lft forever
  1. 默认情况下,Linux 使用第一个 IP 地址作为特定适配器上的源 IP 地址。例如,对于上述系统配置,linux 将使用“100.10.52.15/24”作为源 IP 地址。

  2. 您可以使用“ProcessBuilder”编写java程序来执行以下命令更改IP地址的顺序。(命令:ip addr del 100.10.25.15/24 dev eth0

    ip addr add 100.10.25.15/24 dev eth0)

  3. 删除特定适配器上的所有 IP 地址,将其存储在内存中。按您想要的顺序添加它(应该用作源 ip 的 IP 地址应该首先添加)

  4. 例如,IP 地址“100.10.52.16/24”应该用作源 IP 地址然后

    ip addr del 100.10.25.15/24 dev eth0
    ip addr del 100.10.25.16/24 dev eth0
    
    ip addr add 100.10.25.16/24 dev eth0
    ip addr add 100.10.25.15/24 dev eth0
    
于 2013-10-22T13:40:19.070 回答
-1

好吧,我没有相同的特定答案,但是您可以尝试一下,可能我不确定是否可行,但请尝试一次。

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);
于 2013-10-22T11:44:08.753 回答