Curso Java. Volumen XI. Todo sobre Sockets TCP y UDP en Java

Escrito por Sergio De Luz
Java
1

Ha llegado la hora se hablar sobre TCP y UDP en Java para el intercambio de mensajes. La comunicación se realizará mediante líneas físicas ya sea en red local o a través de internet.

Debido a la lentitud de las líneas de comunicaciones (sobre todo en internet), el intercambio de mensajes es recomendable que sea mínimo de tal forma que obtengamos el máximo rendimiento en nuestro programa, no debemos depender demasiado de dichas comunicaciones.

A continuación tenéis todo lo que necesitáis saber sobre sockets en Java.

Debido a que estamos en una página de redes, y que ya tenéis nuestro particular Curso de Redes, no os vamos a contar las características de TCP y UDP como protocolos de transporte, ni tampoco del protocolo IP, directamente os explicaremos la arquitectura que debemos tener en Java para conseguirlo.

Java proporciona la clase InetAddress para administrar las direcciones IP y los dominios, algunos métodos que podemos encontrar son los siguientes:

  • byte[] getAddress() ; devuelve la dirección IP de un objeto InetAddress.
  • InetAddress getByName(String host) ; devuelve un objeto InetAddress.
  • static InetAddressgetByAddress(byte[] direccion) ; introducimos una dirección IP y nos devuelve un objeto con esa dirección.
  • static InetAddressgetByAddress(String host, byte[] addr) ; igual que el anterior pero también guarda el host.
  • InetAdress getLocalHost() ; devuelve un objeto con la dirección IP local del equipo

A continuación tenéis un ejemplo de todos estos métodos:

package InetAddress;

import java.net.InetAddress;
import java.net.UnknownHostException;
public class DireccionesIP {
public static void main(String[] args) {
byte[] direccionLocal = {127, 0, 0, 1}; //Dirección IP del Localhost
InetAddress equipo;
try {
// Métodos estáticos de InetAddress para obtener el objeto equipo
equipo = InetAddress.getLocalHost();  // Creamos el objeto equipo de la clase InetAddress
System.out.println("Mi equipo es: "+equipo);
System.out.println("Su dirección IP es: "+equipo.getHostAddress());
System.out.println("Su nombre es: "+equipo.getHostName());
System.out.println("Y su nombre canónico: "+equipo.getCanonicalHostName());
System.out.println();

// Obtenemos el equipo a partir del nombre
equipo = InetAddress.getByName("www.google.com");
System.out.println("el equipo www.google.com es: "+equipo);
System.out.println("Su dirección IP es: "+equipo.getHostAddress());
System.out.println("Su nombre es: "+equipo.getHostName());
System.out.println("Y su nombre canónico: "+equipo.getCanonicalHostName());
System.out.println();

// Obtenemos el equipo a partir de su dirección IP
equipo = InetAddress.getByAddress(direccionLocal);
System.out.println("Mi equipo es: "+equipo);
System.out.println("Su dirección IP es: "+equipo.getHostAddress());
System.out.println();

// Obtenemos todas las direcciones IP de un equipo
InetAddress[] identidades;
equipo = InetAddress.getLocalHost();
identidades = InetAddress.getAllByName(equipo.getHostName());
for (int i=0; i<identidades.length; i++) System.out.println("Id"+i+": "+identidades[i]);
System.out.println();

} catch (UnknownHostException e) {
System.out.println("Error de conexión");
System.out.println(e.toString());
}
}
} 

La salida del programa anterior sería esta:

Mi equipo es: -/10.10.2.11
Su dirección IP es: 10.10.2.11
Su nombre es: –
Y su nombre canónico: –

el equipo www.google.com es: www.google.com/173.194.34.240
Su dirección IP es: 173.194.34.240
Su nombre es: www.google.com
Y su nombre canónico: mad01s09-in-f16.1e100.net

Mi equipo es: /127.0.0.1
Su dirección IP es: 127.0.0.1

Id0: -/10.10.2.11
Id1: -/192.168.213.1
Id2: -/192.168.182.1
Id3: -/**%10
Id4: -/**%17
Id5: -/**%18

Ahora vamos a hacer un cliente-servidor TCP para el intercambio de mensajes. Haremos un intercambio de mensajes muy sencillos, las explicaciones están en el propio código pero no tiene ninguna dificultad.

Servidor TCP


package Sockets;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Servidor {

public static void main(String args[]) {
ServerSocket servidor;
Socket conexion;
DataOutputStream salida;
DataInputStream entrada;
int num = 0;
try {
servidor = new ServerSocket(5000); // Creamos un ServerSocket en el puerto especificado
System.out.println("Servidor Arrancado correctamente");
while (true) {
conexion = servidor.accept();     // Esperamos una conexión
num++;
System.out.println("Conexión número" + num + " desde: " + conexion.getInetAddress().getHostName());
entrada = new DataInputStream(conexion.getInputStream());  // Abrimos los canales de entrada y salida
salida = new DataOutputStream(conexion.getOutputStream());
String mensaje = entrada.readUTF();    //Leemos el mensaje del cliente
System.out.println("Conexión n." + num + " mensaje: " + mensaje);
salida.writeUTF("Sois los mejores " + mensaje);  // Le respondemos
conexion.close();                           // Y cerramos la conexión
}
} catch (IOException e) {
}
}
}

Cliente TCP


package Sockets;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

public class Cliente {

public static void main(String args[]) {
Socket cliente;
DataInputStream entrada;
DataOutputStream salida;
String mensaje, respuesta;
try {
cliente = new Socket(InetAddress.getLocalHost(), 5000);   //Creamos el socket para conectarnos al puerto 5000 del servidor
entrada = new DataInputStream(cliente.getInputStream());  //Creamos los canales de entrada/salida
salida = new DataOutputStream(cliente.getOutputStream());
mensaje = "RedesZone";
salida.writeUTF(mensaje);                                 // Enviamos un mensaje al servidor
respuesta = entrada.readUTF();                            // Leemos la respuesta
System.out.println("Mi mensaje: " + mensaje);
System.out.println("Respuesta del Servidor: " + respuesta);
cliente.close();                                          // Cerramos la conexion
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}

Ahora vamos a ver como realizar un programa cliente-servidor con UDP. Este programa es algo más complejo que el anterior, pero en esencia es muy fácil, únicamente que estamos “jugando” con cadenas que pasamos del cliente al servidor por lo que ya lo sabéis.

El programa cliente genera un número aleatorio cada 100ms y lo convierte en una cadena dada y lo envía por el socket UDP para imprimir la cadena que ha enviado (no el número de envío) y comprobaremos si se ha recibido en orden.

Servidor UDP:


package ProgramaJavaCompleto;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ServidorUDP {
public static void main(String[] args) throws SocketException {
DatagramSocket socket = new DatagramSocket(5001); //Creamos el socket UDP
System.out.println("Servidor iniciado correctamente");
int i = 0;
while (true) {
try {
byte[] buf = new byte[128];
DatagramPacket paquete = new DatagramPacket(buf, buf.length); //Formamos el datagrama para empezar a recibir datos
socket.receive(paquete); //Orden para recibir paquetes
String cadena = new String(paquete.getData());
i++;
System.out.println("Recibido de cliente: " + cadena);
String trozo [] = cadena.split(":");
String trozoBueno [] = trozo[0].split("<");
int comprobar = Integer.parseInt(trozoBueno[1]);
if (i == comprobar) {
System.out.println("Correcto");
} else {
System.out.println("Ha habido un error");
}
} catch (IOException ex) {
Logger.getLogger(ClienteUDP.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}

Cliente UDP:


package ProgramaJavaCompleto;

import java.io.IOException;
import java.net.*;

public class ClienteUDP {

public static void main(String[] args) throws SocketException, UnknownHostException, IOException, InterruptedException {
DatagramSocket socket = new DatagramSocket(); //Creamos el socket UDP.
int i = 0;
while (true) {
i++;
Thread.sleep(100);
if (i < 10) {
int aleatorio = (int) (Math.random() * 1000);
String cadena = "<00" + i + ":" + aleatorio + ">";
DatagramPacket paquete = new DatagramPacket(cadena.getBytes(), cadena.length(), InetAddress.getLocalHost(), 5001); //Creamos el datagrama y lo enviamos con los datos señalados (argumentos)
socket.send(paquete);
} else if (i >= 10 && i < 100) {
int aleatorio = (int) (Math.random() * 1000);
String cadena = "<0" + i + ":" + aleatorio + ">";
DatagramPacket paquete = new DatagramPacket(cadena.getBytes(), cadena.length(), InetAddress.getLocalHost(), 5001);
socket.send(paquete);
} else if (i >= 100) {
int aleatorio = (int) (Math.random() * 1000);
String cadena = "<" + i + ":" + aleatorio + ">";
DatagramPacket paquete = new DatagramPacket(cadena.getBytes(), cadena.length(), InetAddress.getLocalHost(), 5001);
socket.send(paquete);
}
}
}
}

Tras estos ejemplos, ya sabéis utilizar sockets TCP y UDP para el intercambio de mensajes, esperamos que os haya gustado y os sirva de ayuda para aprender a programar sockets en Java.


Continúa leyendo
  • josmell jimenez

    DE MARAVILLA HERMANO!! Si que estaba buscando algo con mas potencia en JAVA y realmente esto es DE LUJO!!

    Gracias man.