yo = new ServerSocket(5000); cliente = yo.accept(); |
Asignar los flujos de entrada y salida al socket cliente para poder leer y escribir, aquí la cosa se pone bastante interesante. Para leer un string mandado por el cliente lo queremos hacer con readline() que me regresa directamente un string, no nos gustaría usar readline() de ObjectInputStream porque está desaprobado (deprecated), esto nos deja con readline() de la clase BufferedReader que es el adecuado porque procesa perfectamente los carácteres en Unicode, si vemos en la documentación el constructor de BufferedReader necesita como parámetro un Reader que es superclase de InputStreamReader el cual acepta en su constructor como parámetro un InputStream que es el tipo flujo que se le asigna a un socket por default, estas son las razones para hacer el encadenamiento de flujos que ves en el código, en este caso nos da la ventaja de leer directamente un string en lugar de leer una secuencia de bytes y transformarlo a string, lo cual se puede hacer y lo haremos más adelante con datagramas, pero definitivamente es más conveniente este enfoque.
De la misma manera nos gustaría poder escribir al socket un entero en lugar de mandar los bytes y que los procese el cliente, para esto necesitamos un DataOutputStream que tiene el método writeInt(), aquí la cosa está más directa porque el contructor de DataOutputStream acepta directamente un OutputStream que es el tipo de flujo que se le asigna a un socket por default.
entrada = new BufferedReader(new InputStreamReader(cliente.getInputStream())); salida = new DataOutputStream(cliente.getOutputStream()); |
Después de establecer todo lo necesario para la comunicación, tenemos que realizar nuestro intercambio de datos entre el cliente y el servidor, recordemos que el cliente enviará un string y el servidor le mandará la longitud del string recibido, esto se hará en forma cíclica hasta que el cliente mande un string nulo.
do{ llego = entrada.readLine(); System.out.println("Llego: " + llego); salida.writeInt(llego.length()); }while(llego.length()!=0); |
Finalmente cuando se termina el ciclo, lo único que nos queda es cerrar los flujos y los sockets.
entrada.close(); cliente.close(); yo.close(); |
Cliente2.java
El cliente, después de conectarse con el servidor, leerá del teclado un string dado por el usuario y se lo mandará al servidor, para después leer un entero que debe ser la longitud del string que acaba de mandar.
Declaración de las variables:
Socket yo = null; // Socket para comunicarse con el servidor
PrintWriter alServidor; // Para poder mandar el string leido al servidor con el método println() BufferedReader delTeclado; // Para leer del teclado con el método readLine()
DataInputStream delServidor; // Para poder leer con readInt() el entero que manda el servidor String tecleado; // Almacena el string leido del teclado |
Pedir conexión al servidor y crear el socket yo, para la comunicación. comandos es el arreglo de tipo String que requiere el método main, la conexión se pide al puerto 5000.
yo = new Socket(comandos[0],5000); |
A continuación definimos todos los flujos que necesitaremos. delTeclado es el que me permitirá leer del teclado con el método readLine() que no está desaprobado, System.in es la variable de tipo IntputStream que representa el dispositivo standard de entrada (el teclado). alServidor será el flujo para mandarle al servidor el string leído con el método println(), ademá puedes notar que el constructor, además de un OutputStream requiere un valor booleano, el true indica que el flujo tendré autoflush, que quiere decir que cada vez que se mande un string se mandará inmediatamente y no se almacenará en el buffer intermedio, como normalmente se maneja para hacer más eficiente los flujos, en este caso no queremos eso. Y finalmente delServidor será el flujo que me permita leer del socket un entero mandado por el servidor.
delTeclado = new BufferedReader(new InputStreamReader(System.in)); alServidor = new PrintWriter(yo.getOutputStream(),true); delServidor = new DataInputStream(yo.getInputStream()); |
En el cliente también necesitamos el ciclo que lea un string del teclado, se lo mande al servidor y espere el entero que representa la longitud del string mandado. Este ciclo tambié se repetirá hasta que se haya leído un string de longitud 0 o lo que es lo mismo un string nulo.
do{ System.out.print("Teclea un string: "); tecleado = delTeclado.readLine(); alServidor.println(tecleado); System.out.println("Longitud = "+delServidor.readInt()); }while(tecleado.length()!=0); |