Sockets
Designa un concepto abstracto por el cual dos programas (posiblemente situados en computadoras distintas) pueden intercambiar cualquier flujo de datos, generalmente de manera fiable y ordenada.
Los sockets de Internet constituyen el mecanismo para la entrega de paquetes de datos provenientes de la tarjeta de red a los procesos o hilos apropiados. Un socket queda definido por un par de direcciones IP local y remota, un protocolo de transporte y un par de números de puerto local y remoto.
Protocolos de Transporte
« UDP (User Datagram Protocol): Es un protocolo no orientado a conexión. Es decir cuando una maquina A envía paquetes a una maquina B, el flujo es unidireccional. La transferencia de datos es realizada sin haber realizado previamente una conexión con la máquina de destino (maquina B), y el destinatario recibirá los datos sin enviar una confirmación al emisor (la maquina A). Esto es debido a que la encapsulación de datos enviada por el protocolo UDP no permite transmitir la información relacionada al emisor. Por ello el destinatario no conocerá al emisor de los datos excepto su IP.
« TCP (Transmission Control Protocol): Contrariamente a UDP, el protocolo TCP está orientado a conexión. Cuando una máquina A envía datos a una máquina B, la máquina B es informada de la llegada de datos, y confirma su buena recepción. Aquí interviene el control CRC de datos que se basa en una ecuación matemática que permite verificar la integridad de los datos transmitidos. De este modo, si los datos recibidos son corruptos, el protocolo TCP permite que los destinatarios soliciten al emisor que vuelvan a enviar los datos corruptos.
Socket TCP
Basicamente, este es el funcionamiento de los Socket que necesitamos para una conexión TCP. En el que podemos distinguir dos tipos de Socket el del Servidor y el del Cliente.
La creación del socket en el servidor se remite a crear el socket, indicar por que puerto se harán las escuchas y esperar a la llamada de un cliente para aceptar la conexión, en cambio un cliente creará el socket e indicará donde se encuentra y por que puerto quiere conectarse, de está forma Cliente y Servidor crearán una conexión.
Servidor:
Para crear los socket se crea un objeto del tipo ServerSocket, este método pertenece a la clase java.net.Serversocket
Una vez que hemos creado el objeto socket mandamos un parámetro que indicará el puerto por el que se realzará las comunicaciones.
Para realizar una conexión entre Cliente-Servidor, el servidor usará el método socket.accept para confirmar que se ha iniciado la conexión.
Cliente:
Primero crea un objeto del tipo Socket que pertenece a la clase java.net.Serversocket, Después se obtiene un objeto InetAddress, y usando el método getByName le indicamos donde se va a ejecutar el cliente, en nuestro caso indicamos que será en localhost.
Finalmente creamos un objeto de tipo socket al que pasaremos la dirección donde se está ejecutando el cliente, y el puerto por donde se conectará al servidor.
Ejemplo TCP: El servidor esperará a un cliente y mostrará todos los mensajes que el cliente le envíe. El cliente solo mandará mensajes al servidor, y al escribir la palabra «fin» terminarán ambos programas.
– Servidor TCP:
import java.net.*; //importar la libreria java.net import java.io.*; //importar la libreria java.io // declaramos la clase servidortcp public class servidortcp { // método principal main de la clase public static void main(String argv[]) { // declaramos un objeto ServerSocket para realizar la comunicación ServerSocket socket; // creamos una varible boolean con el valor a false boolean fin = false; // Declaramos un bloque try y catch para controlar la ejecución del subprograma try { // Instanciamos un ServerSocket con la dirección del destino y el // puerto que vamos a utilizar para la comunicación socket = new ServerSocket(6000); // Creamos un socket_cli al que le pasamos el contenido del objeto socket después // de ejecutar la función accept que nos permitirá aceptar conexiones de clientes Socket socket_cli = socket.accept(); // Declaramos e instanciamos el objeto DataInputStream // que nos valdrá para recibir datos del cliente DataInputStream in = new DataInputStream(socket_cli.getInputStream()); // Creamos un bucle do while en el que recogemos el mensaje // que nos ha enviado el cliente y después lo mostramos // por consola do { String mensaje =""; mensaje = in.readUTF(); System.out.println(mensaje); } while (1>0); } // utilizamos el catch para capturar los errores que puedan surgir catch (Exception e) { // si existen errores los mostrará en la consola y después saldrá del // programa System.err.println(e.getMessage()); System.exit(1); } } }
– Cliente TCP:
import java.net.*; // importar la libreria java.net import java.io.*; // importar la libreria java.io // declararamos la clase clientetcp public class clientetcp { // método principal de la clase public static void main(String argv[]) { // Creamos una instancia BuffererReader en la // que guardamos los datos introducido por el usuario BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); // declaramos un objeto socket para realizar la comunicación Socket socket; // declaramos e instanciamos un objeto de tipo byte byte[] mensaje_bytes = new byte[256]; // declaramos una variable de tipo string String mensaje=""; // Declaramos un bloque try y catch para controlar la ejecución del subprograma try { // Instanciamos un socket con la dirección del destino y el // puerto que vamos a utilizar para la comunicación socket = new Socket("127.0.0.1",6000); // Declaramos e instanciamos el objeto DataOutputStream // que nos valdrá para enviar datos al servidor destino DataOutputStream out = new DataOutputStream(socket.getOutputStream()); // Creamos un bucle do while en el que enviamos al servidor el mensaje // los datos que hemos obtenido despues de ejecutar la función // "readLine" en la instancia "in" do { mensaje = in.readLine(); // enviamos el mensaje codificado en UTF out.writeUTF(mensaje); // mientras el mensaje no encuentre la cadena fin, seguiremos ejecutando // el bucle do-while } while (!mensaje.startsWith("fin")); } // utilizamos el catch para capturar los errores que puedan surgir catch (Exception e) { // si existen errores los mostrará en la consola y después saldrá del // programa System.err.println(e.getMessage()); System.exit(1); } } }
Socket UDP:
En este ejemplo vemos que cada paquete de datos podrá tansportar un máximo de 256 bytes por paquete, que es el tamaño máximo que se intercambia el servidor y el cliente.
Además, cuando queremos enviar datos, especificamos el buffer de los datos que queremos enviar, en nuestro caso 256, la longitud máxima de datos, la dirección y el puerto de destino del datagrama. La dirección destino se especifica con el objeto InetAddress, mientras que el puerto es un número entero (6000). El código esta bastante comentado y tiene bastantes explicaciones que pueden ayudaros.
Comentando un poco el código, podemos ver que el cliente para enviar datos usará el método send() de la clase DatagremSocket.
Por otro lado el servidor para recibir datos lo que hace es crear un DatagramSocket para recibir paquetes especificando el número de puerto en el constructor. De esta forma, el servidor estará esperando por el puerto especificado cualquier paquete entrante.
Ejemplo UDP: El servidor esperará a un cliente y mostrará respuesta si se le envía «hola» o «fin». El cliente solo mandará mensajes al servidor, y al escribir la palabra «fin» terminará su ejecución.
– Servidor UDP:
import java.net.*; import java.io.*; public class servidorudp { public static void main(String argv[]) { DatagramSocket socket; boolean fin = false; try { //Creamos el socket socket = new DatagramSocket(6000); byte[] mensaje_bytes = new byte[256]; String mensaje =""; mensaje = new String(mensaje_bytes); String mensajeComp =""; DatagramPacket paquete = new DatagramPacket(mensaje_bytes,256); DatagramPacket envpaquete = new DatagramPacket(mensaje_bytes,256); int puerto; InetAddress address; byte[] mensaje2_bytes = new byte[256]; //Iniciamos el bucle do { // Recibimos el paquete socket.receive(paquete); // Lo formateamos mensaje = new String(mensaje_bytes).trim(); // Lo mostramos por pantalla System.out.println(mensaje); //Obtenemos IP Y PUERTO puerto = paquete.getPort(); address = paquete.getAddress(); if (mensaje.startsWith("fin")) { mensajeComp="chauuuuuuu cliente"; } if (mensaje.startsWith("hola")) { mensajeComp="hola cliente"; } //formateamos el mensaje de salida mensaje2_bytes = mensajeComp.getBytes(); //Preparamos el paquete que queremos enviar envpaquete = new DatagramPacket(mensaje2_bytes,mensajeComp.length(),address,puerto); // realizamos el envio socket.send(envpaquete); } while (1>0); } catch (Exception e) { System.err.println(e.getMessage()); System.exit(1); } } }
– Cliente UDP:
import java.net.*; import java.io.*; //declaramos la clase udp public class clienteudp { public static void main(String argv[]) { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); //Definimos el sockets, número de bytes del buffer, y mensaje. DatagramSocket socket; InetAddress address; byte[] mensaje_bytes = new byte[256]; String mensaje=""; mensaje_bytes=mensaje.getBytes(); //Paquete DatagramPacket paquete; String cadenaMensaje=""; DatagramPacket servPaquete; byte[] RecogerServidor_bytes = new byte[256]; try { socket = new DatagramSocket(); address=InetAddress.getByName("localhost"); do { mensaje = in.readLine(); mensaje_bytes = mensaje.getBytes(); paquete = new DatagramPacket(mensaje_bytes,mensaje.length(),address,6000); socket.send(paquete); RecogerServidor_bytes = new byte[256]; //Esperamos a recibir un paquete servPaquete = new DatagramPacket(RecogerServidor_bytes,256); socket.receive(servPaquete); //Convertimos el mensaje recibido en un string cadenaMensaje = new String(RecogerServidor_bytes).trim(); //Imprimimos el paquete recibido System.out.println(cadenaMensaje); } while (!mensaje.startsWith("fin")); } catch (Exception e) { System.err.println(e.getMessage()); System.exit(1); } } }