如何从httpclient连接获取底层Socket?

时间:2016-08-31 16:22:25

标签: java sockets apache-httpclient-4.x

这个问题与SO上的另一个问题(HttpClient: how do I obtain the underlying socket from an existing connection?)的措辞相同,但问题实际上是关于通过HTTP(S)隧道化其他协议,因此答案有点不同。

我尝试做的是建立HTTPS连接,然后找出该连接的详细信息。 Java的SSLSocket课程会给我我需要的东西,但我需要能够掌握Socket本身才能查询它。

有没有办法到达基础Socket? httpclient / httpcore已经成为工厂和私有/受保护实现的迷宫,所以很难围绕API来确定如何在配置后实际获取内容。

2 个答案:

答案 0 :(得分: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());
}

答案 1 :(得分: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());
        }
    }
}