Saltar al contenido

Protocolo de Blog de notas remoto versi贸n 4 | TPC

25 de marzo 2016

Buenas, hoy os traigo un c贸digo Java que utiliza el protocolo TPC para comunicarse con un Bloc de notas. Este desarrollo nos lo pidi贸 que se lo hiciesemos hace un par de d铆as un lector del blog 芦Daniel Ruiz禄 estudiante de la Universidad de Sevilla, en concreto de la ESCUELA T脡CNICA SUPERIOR DE INGENIER脥A INFORM脕TICA.

Ten铆a el c贸digo del protocolo UDP pero no estaba bien estructurado, y obviamente no pod铆a funcionar correctamente. Despu茅s de solicitar nuestra ayuda y acudir como el Equipo A, os dejo los resultados en forma de post.

Tuvimos que hacer algunos cambios y unas cuantas explicaciones que a continuaci贸n os dejo. Este el c贸digo del desarrollo que finalmente hicimos para 茅l. Por si ha alguien m谩s le vale.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
 
public class TCPCliente {
    public static void main(String [] args) throws Exception{
        String usuario = null;
        String opcion;
        String opcion2;
        String mensaje = null;
        String clave = null;
        String A_PDU;
        boolean autenticado = false;
        boolean salir = false;
 
        BufferedReader entradaDesdeUsuario = new BufferedReader(new InputStreamReader(System.in));
 
        InetAddress direccionIP = InetAddress.getByName("gauss.dte.us.es");
 
        Socket socketTCP = new Socket(direccionIP, 56794);
        socketTCP.setSoTimeout(3000);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socketTCP.getInputStream()));
        PrintWriter printWriter = new PrintWriter(socketTCP.getOutputStream(), true);
 
        System.out.println("******************************* Bienvenido *******************");
        System.out.println("*                                                            *");
        System.out.println("*    El cliente Bloc de notas remoto v4 usa el puerto: 33096  ");
        System.out.println("*                                                            *");
        System.out.println("*                                                             ");
        System.out.println("                                                              ");
        System.out.println("**************************************************************");
        System.out.println("             Debe de validar su cuenta de usuario:");
        System.out.println("");
 
        while (!salir) {
 
            if (!autenticado) {
                System.out.println("Elija una opci贸n (Men煤 M1):");
                System.out.println("");
                System.out.println("   1.Autenticar");
                System.out.println("   2.Salir");
                opcion = entradaDesdeUsuario.readLine();
 
                if (opcion.equals("1")) {
                    System.out.println("Introduzca el nombre de usuario:");
                    usuario = entradaDesdeUsuario.readLine();
                    System.out.println("");
                    System.out.println("Introduzca su clave:");
                    clave = entradaDesdeUsuario.readLine();
                    A_PDU = "aut " + usuario + " " + clave;
 
// Personalmente me gusta m谩s esta clase porque me desentiendo de tener que indicar el fin del env铆o (CRLF)
                    printWriter.println(A_PDU);
// Pero se puede usar esta otra forma, que simplemente usa un outputstream e indicar que los 煤ltimos bytes ser谩n el indicador del fin del env铆o de este paquete TCP (con CRLF)
//                    socketTCP.getOutputStream().write((A_PDU + "\r\n").getBytes());
                    System.out.println("Espere un momento por favor.");
 
                    try{
                        String respuesta = bufferedReader.readLine();
 
                        if (respuesta.contains("01")) {
                            autenticado = true;
                            System.out.println(respuesta);
                        } else {
                            System.out.println("Se ha producido un error: " + respuesta);
                        }
                    }catch(SocketTimeoutException e){
                        System.out.println("El servidor no responde. Vuelva a intentarlo.");
                    }
 
 
 
                } else if (opcion.equals("2")) {
                    System.out.println("Usted ha seleccionado Salir por lo que la conexi贸n se ha cerrado.");
                    salir = true;
                } else {
                    System.out.println("No ha introducido ninguna de las opciones posibles, vuelva a intentarlo.");
                }
            } else {
                System.out.println("Elija una opci贸n (Men煤 M2):");
                System.out.println("");
                System.out.println("   1.Solicitar bloc de notas");
                System.out.println("   2.Modificar bloc de notas");
                System.out.println("   3.Salir");
                opcion2 = entradaDesdeUsuario.readLine();
 
                if (opcion2.equals("3")) {
                    System.out.println("Usted ha seleccionado Salir por lo que la conexi贸n se ha cerrado.");
                    salir=true;
 
                } else if (opcion2.equals("2")) {
                    System.out.println("Introduzca el texto:");
                    mensaje = entradaDesdeUsuario.readLine();
 
                    A_PDU = "put " + usuario + " " + clave + " " + mensaje;
 
                    printWriter.println(A_PDU);
 
                    System.out.println("Espere un momento por favor.");
 
                    try{
                        String respuesta = bufferedReader.readLine();
                        if (respuesta.contains("02")) {
                            autenticado = true;
                            System.out.println(respuesta);
                        } else {
                            System.out.println("Se ha producido un error: " + respuesta);
                        }
                    }catch(SocketTimeoutException e){
                        System.out.println("El servidor no responde. Vuelvalo a intentar.");
                    }
 
 
                } else if (opcion2.equals("1")) {
                    A_PDU = "get " + usuario + " " + clave;
 
                    printWriter.println(A_PDU);
 
                    System.out.println("Espere un momento por favor.");
 
                    try{
                        String respuesta = bufferedReader.readLine();
                        if (respuesta.contains("03")) {
                            autenticado = true;
                            System.out.println(respuesta);
                        } else {
                            System.out.println("Se ha producido un error: " + respuesta);
                        }
                    }catch(SocketTimeoutException e){
                        System.out.println("El servidor no responde. Vuelvalo a intentar.");
                    }
                } else {
                    System.out.println("No ha introducido ninguna de las opciones posibles, vuelva a intentarlo.");
                }
            }
        }
        socketTCP.close();
    }
}

Comentarios adicionales

1) He mantenido la misma estructura que se usaba en UDP para que se pueda centrar en los cambios.

2) La estructura de UDP es perfectamente v谩lida para TCP. Sin embargo, para UDP yo usar铆a una variable que mantiene lo 煤ltimo enviado y estar铆a leyendo constantemente en un bucle. De esta forma, la p茅rdida de un paquete no afectar铆a el funcionamiento del resto de la clase.

3) He usado la clase BufferedReader en vez de ir leyendo simplemente del inputstream. Esta clase nos permite ir leyendo l铆nea a l铆nea del servidor y no tener que preocuparnos por el n煤mero de bytes de la respuesta met铆endolos en un array de longitud determinada, ya que udp tiene el tama帽o del paquete limitado pero TCP no. No obstante, se puede usar el InputStream y el array, igual que se hac铆a al leer UDP.

4) He usado la clase PrintWriter en vez de la clase OutputStream. PrintWriter envuelve dicha clase y nos permite despreocuparnos de tener que indicar el final de cada env铆o con un CRLF. He puesto un ejemplo de como se har铆a tambi茅n con un OutputStream directamente en el primer env铆o.

5) Al no tener usuario, s贸lo he podido comprobar a tratar de autenticar y que me tire para atr谩s. La l贸gica del resto (que es la misma de UDP) parece estar correcta pero no he podido probarla. Es posible que en las respuestas haya que leer el BufferedReader hasta que est茅 vac铆o ya que, por el documento del protocolo, se env铆a informaci贸n separada por un CRLF. En dicho caso, al leer, bastar铆a con hacer un bucle while y usar el readLine hasta que devuelva null.

teoremaCAP

Otros usuarios llegaron aqu铆 buscando:

PROTOCOLO DE BLOC DE NOTAS REMOTO versi贸n 4
PROGRAMA REDES DE COMPUTADORES
ESPECIFICACI脫N DE PROTOCOLOS