2016-08-31 7 views
0

Этот вопрос сформулирован так же, как и другой вопрос о SO (HttpClient: how do I obtain the underlying socket from an existing connection?), но этот вопрос на самом деле связан с туннелированием других протоколов через HTTP (S), и, таким образом, ответ немного отличается.Как получить базовый Socket из соединения httpclient?

То, что я пытаюсь сделать, это установить HTTPS-соединение, а затем узнать подробности этого соединения. Класс Java SSLSocket даст мне то, что мне нужно, но я должен уметь удерживать Socket сам, чтобы его опросить.

Есть ли способ добраться до базового Socket? httpclient/httpcore стал лабиринтом фабрик и частных/защищенных реализаций вещей, поэтому очень сложно сориентироваться API, чтобы выяснить, как на самом деле получить вещи, как только они были настроены.

+0

Какую информацию вы ищете именно в розетке? Если 'HttpClient' не предоставляет доступ к его объекту' Socket', вы можете просто использовать '(SSL) Socket' непосредственно для реализации HTTP (S) вручную. –

+0

Вы не можете. Единственный способ разоблачить созданные sokets - это обеспечить собственную фабрику сокетов и хранить ссылки на созданные сокеты самостоятельно. – Antoniossss

+0

@RemyLebeau Я ищу протокол TLS и набор шифров, согласованный с TLS. Я ограничил те, которые * могут * быть согласованы, но я хотел бы зарегистрировать те, которые были фактически выбраны для разговора. –

ответ

0

В итоге я использовал несколько другую технику, но @oleg получил меня на правильном пути. Вот мой единовременный код:

HttpClientContext ctx = HttpClientContext.create(); 
HttpResponse response = getHttpClient().execute(method, ctx); 

if(log.isDebugEnabled()) 
{ 
    ManagedHttpClientConnection connection = ctx.getConnection(ManagedHttpClientConnection.class); 
    // Can be null if the response encloses no content 
    if(null != connection) 
    { 
     Socket socket = connection.getSocket(); 
     if(socket instanceof SSLSocket) 
     { 
      SSLSocket sslSock = (SSLSocket)socket; 
      log.debug("Connected to " + getEndpointURL() 
         + " using " + sslSock.getSession().getProtocol() 
         + " and suite " + sslSock.getSession().getCipherSuite()); 
     } 
    } 
} 
1

HttpClient намеренно затрудняет доступ к базовому объекту подключения и к сокету, к которому он привязан, в первую очередь для обеспечения согласованности состояния соединения и постоянных подключений в пуле соединений, которые могут быть повторно использованы другой транзакцией ,

Однако можно получить базовое соединение от ответного перехватчика.

CloseableHttpClient httpclient = HttpClients.custom() 
     .addInterceptorLast(new HttpResponseInterceptor() { 
      @Override 
      public void process(
        final HttpResponse response, 
        final HttpContext context) throws HttpException, IOException { 
       HttpClientContext clientContext = HttpClientContext.adapt(context); 
       ManagedHttpClientConnection connection = clientContext.getConnection(ManagedHttpClientConnection.class); 
       // Can be null if the response encloses no content 
       if (connection != null) { 
        Socket socket = connection.getSocket(); 
        System.out.println(socket); 
       } 

      } 
     }) 
     .build(); 
try (CloseableHttpResponse response = httpclient.execute(new HttpGet("http://www.google.com/"))) { 
    System.out.println(response.getStatusLine()); 
    EntityUtils.consume(response.getEntity()); 
} 
+0

Как только у вас есть 'Socket', вы можете привести его в' SSLSocket' и получить его 'SSLSession', который затем может сообщить вам согласованный протокол SSL и набор шифров, которые используются. –

+0

Я сейчас пытаюсь попробовать. Когда я набираю код, мне приходит в голову, что этот перехватчик, скорее всего, срабатывает для каждого ответа, который я получаю ... поэтому, если я использую HTTP keep-alive и соединение остается открытым, мой перехватчик будет срабатывать для каждого запроса, а не только тогда, когда Совпадение TLS завершено. Я должен учитывать это при написании кода, чтобы избежать многократного ввода информации о TLS. –

+0

@RemyLebeau Да, я знаю, как отдать сокет в SSLSocket и получить параметры протокола. Я просто не знал, как получить сам сокет. –