Заставить Okhttp3 привязаться к конкретному локальному адресу - PullRequest
1 голос
/ 17 июня 2019

Я хотел бы связать HTTP-клиентские соединения, исходящие через okhttp3, для выхода из определенного сетевого интерфейса. Будет много виртуальных сетевых адаптеров, настроенных на ВМ, и правила брандмауэра будут конкретными. Итак, я хочу контролировать, какой vNIC использовать для этого. У меня тоже правильно рассчитан InetAddress.

Также. Я пробовал решение, предложенное в Глобальное состояние и локальный адрес в OkHttp , но все еще получаю ConnectionException. Может кто-нибудь подсказать, чего мне не хватает, чтобы заставить его работать?

      OkHttpClient okclient = new OkHttpClient.Builder()
              .retryOnConnectionFailure(false)
              .socketFactory(new CustomSocketFactory())
              .build();
      Request req = new Request.Builder()
              .url("http://www.google.com")
              .get()
              .build();
      Response rsp = okclient.newCall(req).execute();

Ниже приведен CustomSocketFactory, который почти идентичен тому, который был задан вышеупомянутым вопросом stackoverflow, который я упоминал выше.

class CustomSocketFactory extends SocketFactory
{
    private static final String ERROR_MSG = "Only unconnected sockets are supported";
    final SocketFactory defaultSocketFactory;
    final InetAddress localAddress;
    final int localPort = 0;

    public CustomSocketFactory() throws Exception
    {
        System.out.println("[creating a custom socket factory]");
        localAddress = InetAddress.getLocalHost();
        defaultSocketFactory = SocketFactory.getDefault();
    }

    @Override
    public Socket createSocket() throws IOException
    {
        System.out.println("I am here");
        Socket s = defaultSocketFactory.createSocket();
        s.bind(new InetSocketAddress(localAddress, localPort));
        return s;
    }

    @Override
    public Socket createSocket(final String remoteAddress, final int remotePort)
    {
        throw new UnsupportedOperationException(ERROR_MSG);
    }

    @Override
    public Socket createSocket(final InetAddress remoteAddress, final int remotePort)
    {
        throw new UnsupportedOperationException(ERROR_MSG);
    }

    @Override
    public Socket createSocket(final String remoteAddress,
                               final int remotePort,
                               final InetAddress localAddress,
                               final int localPort)
    {
        throw new UnsupportedOperationException(ERROR_MSG);
    }

    @Override
    public Socket createSocket(final InetAddress remoteAddress,
                               final int remotePort,
                               final InetAddress localAddress,
                               final int localPort)
    {
        throw new UnsupportedOperationException(ERROR_MSG);
    }

}


Error received: 

java.net.ConnectException: Connection refused (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at java.net.Socket.connect(Socket.java:538)
    at java.net.Socket.<init>(Socket.java:434)
    at java.net.Socket.<init>(Socket.java:244)
    at javax.net.DefaultSocketFactory.createSocket(SocketFactory.java:277)
    at com.okhttp3.CustomSocketFactory.createSocket(TestOkClient.java:74)
    at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:257)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:183)
    at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.java:224)
    at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.java:108)
    at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.java:88)
    at okhttp3.internal.connection.Transmitter.newExchange(Transmitter.java:169)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:41)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:221)
    at okhttp3.RealCall.execute(RealCall.java:81)
    at com.okhttp3.TestOkClient.main(TestOkClient.java:40)

1 Ответ

0 голосов
/ 18 июня 2019

Это выглядит в основном правильно, зачем использовать петлевое устройство InetAddress.getLocalHost()?

Это аналогичное решение https://github.com/yschimke/okurl/blob/master/src/main/kotlin/com/baulsupp/okurl/network/InterfaceSocketFactory.kt

...