简体   繁体   English

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

[英]How can I get the underlying Socket from an httpclient connection?

This question is worded the same way as another question on SO ( HttpClient: how do I obtain the underlying socket from an existing connection? ), but that question is actually about tunneling other protocols through HTTP(S) and thus the answer is quite a bit different.这个问题的措辞与 SO 上的另一个问题( HttpClient:如何从现有连接中获取底层套接字? )的措辞相同,但该问题实际上是关于通过 HTTP(S) 隧道传输其他协议,因此答案是相当有点不同。

What I'm trying to do is make an HTTPS connection, then find out the details of that connection.我要做的是建立一个 HTTPS 连接,然后找出该连接的详细信息。 Java's SSLSocket class will give me what I need, but I need to be able to get a hold of the Socket itself in order to interrogate it. Java 的SSLSocket类会给我我需要的东西,但我需要能够掌握Socket本身以便查询它。

Is there a way to get to the underlying Socket ?有没有办法访问底层的Socket httpclient/httpcore has become a maze of factories and private/protected implementations of things, so it's really difficult to poke-around the API to figure out how to actually get things once they have been configured. httpclient/httpcore 已经变成了工厂和私有/受保护实现的迷宫,因此在 API 被配置后,很难弄清楚如何实际获取这些 API。

HttpClient intentionally makes it difficult to get hold of the underlying connection object and the socket it is bound to, primarily to ensure the connection state is consistent and persistent connections in the connection pool are safe to be re-used by another transaction. HttpClient 故意使获取底层连接对象及其绑定的套接字变得困难,主要是为了确保连接状态一致并且连接池中的持久连接可以安全地被另一个事务重用。

However, one can get hold of the underlying connection from a response interceptor.但是,可以从响应拦截器获取底层连接。

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

I ended up using a somewhat different technique, but @oleg got me on the right track.我最终使用了一种稍微不同的技术,但 @oleg 使我走上了正确的道路。 Here's my one-time code:这是我的一次性代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM