es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo mantener una conexión persistente entre dos servicios web y establecer una conexión dúplex.

Declaración del problema –

Tengo el requerimiento de hacer una conexión SSL de salida desde detrás del firewall hacia el servicio web en la nube externa y mantener esa conexión abierta para la comunicación dúplex, para facilitar la comprensión estoy dividiendo este requisito en 2 fases como se muestra a continuación.

Fase 1 –

Tengo un agente que está instalado y se ejecuta detrás del firewall del cliente, y se conectará al servicio web en la nube externa abriendo una conexión en el puerto 443.

He intentado 2 maneras –

1- Cliente de zócalo SSL

En este enfoque, después de cada ciclo de solicitud-respuesta, la conexión se cierra, y para cada nueva solicitud, necesito volver a abrir la conexión nuevamente.

Para evitar el problema de reabrir la conexión, intenté usar la biblioteca Apache commons-httpclient

2- Creando una conexión HTTP utilizando la biblioteca apache commons-httpclient

Esto resuelve mi problema de volver a abrir la conexión cada vez, crea DefaultHttpClient una vez y podemos reutilizarlo cualquier número de veces.

Fase 2 –

La fase 2 de mi problema consiste en mantener esa conexión. Eso significa que mi fuente de servicio web ha creado una conexión como el método descrito anteriormente y esa misma conexión debería ser utilizada por el servicio web de destino, si es necesario solicitar algo en el futuro, es necesario crear algún tipo de gancho o devolución de llamada para abrir la comunicación en dos sentidos o diría una comunicación dúplex.

Para resolver esto, intenté usar AsyncClientHttpExchange.

Pero nuevamente no resolverá mi problema de devolución de llamada / gancho. Leí este artículo, en realidad, necesito el mismo comportamiento.

Llamando de vuelta El servidor toma la iniciativa después de completar un trabajo y se transforma en un cliente haciendo una solicitud HTTP al cliente original (que actúa ahora como un servidor, por supuesto). El protocolo debe ser compartido (como solicitudes PUT o POST con un cierto formato).

Espero alguna referencia de código para implementar este comportamiento.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Solución para conexión SSL saliente para comunicación dúplex

    Declaración del problema

    El problema consiste en crear una conexión SSL saliente detrás del firewall hacia el servicio web externo en la nube, y mantener esa conexión abierta para la comunicación dúplex. El requisito se divide en dos fases:

    Fase 1

    Crear un agente instalado detrás del firewall del cliente, que se conecte al servicio web externo en la nube abriendo una conexión en el puerto 443. Hay dos formas de hacerlo:

    Opción 1 – Cliente de Socket SSL

    El enfoque del Cliente de Socket SSL crea una nueva conexión para cada ciclo de solicitud-respuesta, lo que puede causar problemas con el tiempo y los recursos. El código de ejemplo para este enfoque es:

    public class SSLSocketClient {
        public static void main(String[] args) throws Exception {
            try {
                SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
                SSLSocket socket = (SSLSocket)factory.createSocket("mycloud.com", 443);
                socket.setKeepAlive(true);
                socket.startHandshake();
                boolean isLive = true;
    
                PrintWriter out = new PrintWriter(
                                      new BufferedWriter(
                                      new OutputStreamWriter(
                                      socket.getOutputStream())));
    
                out.println("GET /some/orgs/myorg HTTP/1.1");
                out.println("Host: mycloud.com");
                out.println("Accept: application/json");
                out.println("X-Api-Key: knwysf24tzeatwk5dwnqa6xh");
    
                out.println();
                out.flush();
    
                if (out.checkError())
                    System.out.println("SSLSocketClient:  java.io.PrintWriter error");
    
                BufferedReader in = new BufferedReader(
                                        new InputStreamReader(
                                        socket.getInputStream()));
    
                String inputLine;
                while ((inputLine = in.readLine()) != null)
                    System.out.println(inputLine);
    
                in.close();
                out.close();
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    Opción 2 – Biblioteca Apache Commons-HttpClient

    La biblioteca Apache Commons-HttpClient permite la reutilización de la conexión y reduce el uso de los recursos. El código de ejemplo para este enfoque es:

    public class HttpClientTest {
        private static int connectionTimeout = 1000;
        private static int socketTimeout = 10000;
        private static String host = "mycloud.com";
        private static int port = 443;
        static boolean  useExpectContinue = true;
    
        public static DefaultHttpClient configureClient() {
            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setUseExpectContinue(params, useExpectContinue);
            HttpConnectionParams.setConnectionTimeout(params, connectionTimeout);
            HttpConnectionParams.setSoTimeout(params, socketTimeout);
            HttpConnectionParams.setTcpNoDelay(params, Boolean.TRUE);
    
            String protocol = "https";
            params.setParameter(ClientPNames.DEFAULT_HOST, new HttpHost(host, port, protocol));
            DefaultHttpClient client = new DefaultHttpClient(params);
    
            return client;
        }
    
        public static void main(String args []) throws IOException {
            String uri = "/idbridge/orgs/cableco_rt";
            HttpGet httpGet = new HttpGet(uri);
            httpGet.setHeader("Host",host);
            httpGet.setHeader("Accept","application/json");
            httpGet.setHeader("X-Api-Key","knwysf24tzeatwk5dwnqa6xh");
    
            String uriOrg = "/idbridge/orgs";
            HttpGet httpGetOrg = new HttpGet(uriOrg);
            httpGetOrg.setHeader("Host",host);
            httpGetOrg.setHeader("Accept","application/json");
            httpGetOrg.setHeader("X-Api-Key","knwysf24tzeatwk5dwnqa6xh");
    
            DefaultHttpClient client = configureClient();
            HttpParams params = client.getParams();
    
            System.out.println("Client connected to -> " + params.getParameter("http.default-host"));
    
            System.out.println("Request -> " + httpGet.getURI());
    
            HttpResponse rsp = client.execute(httpGet);
    
            HttpEntity entity = rsp.getEntity();
            Header[] allHeaders = rsp.getAllHeaders();
            System.out.println("Response : " + EntityUtils.toString(entity,"UTF-8"));
    
            HttpResponse rspOrg = client.execute(httpGetOrg);
            System.out.println("Request -> " + httpGetOrg.getURI());
    
            HttpEntity entityOrg = rspOrg.getEntity();
            Header[] allHeadersOrg = rspOrg.getAllHeaders();
            System.out.println("Response : " + EntityUtils.toString(entityOrg,"UTF-8"));
        }   
    }
    

    Fase 2

    La segunda fase requiere mantener la conexión y permitir la comunicación dúplex. El código de ejemplo para este enfoque es:

    Opción 1 – AsyncClientHttpExchange

    El enfoque AsyncClientHttpExchange proporciona una solución simple para crear un intercambio HTTP asíncrono, pero no permite una comunicación dúplex. El código de ejemplo para este enfoque es:

    public class AsyncClientHttpExchange {
        public static void main(final String[] args) throws Exception {
            CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
            try {
                httpclient.start();
                HttpGet request = new HttpGet("http://localhost:9090/connect");
                Future<httpresponse> future = httpclient.execute(request, null);
                HttpResponse response = future.get();
                System.out.println(EntityUtils.toString(response.getEntity(),"UTF-8"));
                System.out.println("Response: " + response.getStatusLine());
                System.out.println("Shutting down");
            } finally {
                httpclient.close();
            }
            System.out.println("Done");
        }       
    }
    

    Opción 2 – Rest-Callbacks

    Los Rest-Callbacks proporcionan una solución para mantener una conexión abierta para la comunicación dúplex. El servidor inicia un trabajo y se transforma en cliente, haciendo una solicitud HTTP al cliente original (que ahora actúa como servidor). Este protocolo se debe compartir, como las solicitudes PUT o POST con un formato determinado. No se proporciona un código de ejemplo para este enfoque, ya que dependerá de la implementación y los requisitos específicos.

    Conclusión

    En conclusión, existen varias formas de crear una conexión SSL saliente y mantener una conexión abierta para comunicación dúplex. La elección del enfoque dependerá de los requisitos específicos del proyecto, y el enfoque Rest-Callbacks puede ser la mejor opción para algunos proyectos.

Comments are closed.