gentoo linux, java, software libre y otras hierbas
abr, 02 2008 - 1:03 pm

[código] Uso de Datagramas en Java (Protocolo UDP)

Hace un rato ponía un ejemplo acerca del uso de Sockets en Java, para enviar y recibir datos vía red (TCP). Esta vez haremos algo similar pero usando Datagramas, es decir, usando UDP.

UDP es un protocolo no orientado a la conexión. Esto significa que la comunicación es más rápida (porque no hay que establecer conexiones ni circuitos virtuales entre máquinas) pero también menos segura, puesto que a diferencia del TCP no mantiene estado de conexión alguno. (Leer más acerca de las diferencias entre UDP y TCP).

Para dicho propósito, el programa hace uso de las clases DatagramSocket y DatagramPacket. Esta clase representa a los paquetes de datos que vamos a recibir o transmitir a través de los objetos DatagramSocket. Estos paquetes constan de una cabecera (que incluye la dirección de origen y destino del paquete, el puerto, la longitud del paquete, un checksum, etc.) y un cuerpo (donde se encuentra el contenido real del paquete) [?].

El resultado…

El código…

La clase Servidor.java:

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Servidor extends JFrame {
   private JTextArea areaPantalla;
   private DatagramSocket socket;
   // configurar GUI y DatagramSocket
   public Servidor()
   {
      super( "Servidor" );
      areaPantalla = new JTextArea();
      getContentPane().add( new JScrollPane( areaPantalla ),
         BorderLayout.CENTER );
      setSize( 400, 300 );
      setVisible( true );
      // crear objeto DatagramSocket para enviar y recibir paquetes
      try {
         socket = new DatagramSocket( 5000 );
      }
      // procesar los problemas que pueden ocurrir al crear el objeto DatagramSocket
      catch( SocketException excepcionSocket ) {
         excepcionSocket.printStackTrace();
         System.exit( 1 );
      }
   } // fin del constructor de Servidor
   // esperar a que lleguen los paquetes, mostrar los datos y repetir el paquete al cliente
   private void esperarPaquetes()
   {
      while ( true ) { // iterar infinitamente
         // recibir paquete, mostrar su contenido, devolver copia al cliente
         try {
            // establecer el paquete
            byte datos[] = new byte[ 100 ];
            DatagramPacket recibirPaquete =
               new DatagramPacket( datos, datos.length );
            socket.receive( recibirPaquete ); // esperar el paquete
            // mostrar la información del paquete recibido
            mostrarMensaje( "\nPaquete recibido:" +
               "\nDel host: " + recibirPaquete.getAddress() +
               "\nPuerto del host: " + recibirPaquete.getPort() +
               "\nLongitud: " + recibirPaquete.getLength() +
               "\nContenido:\n\t" + new String( recibirPaquete.getData(),
                  0, recibirPaquete.getLength() ) );
            enviarPaqueteACliente( recibirPaquete ); // enviar paquete al cliente
         }
         // procesar los problemas que pueden ocurrir al manipular el paquete
         catch( IOException excepcionES ) {
            mostrarMensaje( excepcionES.toString() + "\n" );
            excepcionES.printStackTrace();
         }
      } // fin de instrucción while
   } // fin del método esperarPaquetes
   // repetir el paquete al cliente
   private void enviarPaqueteACliente( DatagramPacket recibirPaquete )
      throws IOException
   {
      mostrarMensaje( "\n\nRepitiendo datos al cliente..." );
      // crear paquete a enviar
      DatagramPacket enviarPaquete = new DatagramPacket(
         recibirPaquete.getData(), recibirPaquete.getLength(),
         recibirPaquete.getAddress(), recibirPaquete.getPort() );
      socket.send( enviarPaquete ); // enviar el paquete
      mostrarMensaje( "Paquete enviado\n" );
   }
   // método utilitario que es llamado desde otros subprocesos para manipular a
   // areaPantalla en el subproceso despachador de eventos
   private void mostrarMensaje( final String mensajeAMostrar )
   {
      // mostrar el mensaje del subproceso de ejecución despachador de eventos
      SwingUtilities.invokeLater(
         new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
            public void run() // actualiza areaPantalla
            {
               areaPantalla.append( mensajeAMostrar );
               areaPantalla.setCaretPosition(
                  areaPantalla.getText().length() );
            }
         }  // fin de la clase interna
      ); // fin de la llamada a SwingUtilities.invokeLater
   }
   public static void main( String args[] )
   {
      JFrame.setDefaultLookAndFeelDecorated(true);
      Servidor aplicacion = new Servidor();
      aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      aplicacion.esperarPaquetes();
   }
} // fin de la clase Servidor

La clase Cliente.java:

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Cliente extends JFrame {
   private JTextField campoIntroducir;
   private JTextArea areaPantalla;
   private DatagramSocket socket;
   // configurar GUI y DatagramSocket
   public Cliente()
   {
      super( "Cliente" );
      Container contenedor = getContentPane();
      campoIntroducir = new JTextField( "Escriba aquí el mensaje" );
      campoIntroducir.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent evento )
            {
               // crear y enviar el paquete
               try {
                  areaPantalla.append( "\nEnviando paquete que contiene: " +
                     evento.getActionCommand() + "\n" );
                  // obtener mensaje del campo de texto y convertirlo en arreglo byte
                  String mensaje = evento.getActionCommand();
                  byte datos[] = mensaje.getBytes();
                  // crear enviarPaquete
                  DatagramPacket enviarPaquete = new DatagramPacket( datos,
                     datos.length, InetAddress.getLocalHost(), 5000 );
                  socket.send( enviarPaquete ); // enviar paquete
                  areaPantalla.append( "Paquete enviado\n" );
                  areaPantalla.setCaretPosition(
                     areaPantalla.getText().length() );
               }
               // procesar los problemas que pueden ocurrir al crear o enviar el paquete
               catch ( IOException excepcionES ) {
                  mostrarMensaje( excepcionES.toString() + "\n" );
                  excepcionES.printStackTrace();
               }
            } // fin de actionPerformed
         } // fin de la clase interna
      ); // fin de la llamada a addActionListener
      contenedor.add( campoIntroducir, BorderLayout.NORTH );
      areaPantalla = new JTextArea();
      contenedor.add( new JScrollPane( areaPantalla ),
         BorderLayout.CENTER );
      setSize( 400, 300 );
      setVisible( true );
      // crear objeto DatagramSocket para enviar y recibir paquetes
      try {
         socket = new DatagramSocket();
      }
      // atrapar los problemas que pueden ocurrir al crear objeto DatagramSocket
      catch( SocketException excepcionSocket ) {
         excepcionSocket.printStackTrace();
         System.exit( 1 );
      }
   } // fin del constructor de Cliente
   // esperar a que lleguen los paquetes del Servidor, mostrar el contenido de los paquetes
   private void esperarPaquetes()
   {
      while ( true ) { // iterar infinitamente
         // recibir el paquete y mostrar su contenido
         try {
            // establecer el paquete
            byte datos[] = new byte[ 100 ];
            DatagramPacket recibirPaquete = new DatagramPacket(
               datos, datos.length );
            socket.receive( recibirPaquete ); // esperar un paquete
            // mostrar el contenido del paquete
            mostrarMensaje( "\nPaquete recibido:" +
               "\nDel host: " + recibirPaquete.getAddress() +
               "\nPuerto del host: " + recibirPaquete.getPort() +
               "\nLongitud: " + recibirPaquete.getLength() +
               "\nContenido:\n\t" + new String( recibirPaquete.getData(),
                  0, recibirPaquete.getLength() ) );
         }
          // procesar los problemas que pueden ocurrir al recibir o mostrar el paquete
         catch( IOException excepcion ) {
            mostrarMensaje( excepcion.toString() + "\n" );
            excepcion.printStackTrace();
         }
      } // fin de instrucción while
   } // fin del método esperarPaquetes
   // método utilitario que es llamado desde otros subprocesos para manipular a
   // areaPantalla en el subproceso despachador de eventos
   private void mostrarMensaje( final String mensajeAMostrar )
   {
      // mostrar mensaje del subproceso de ejecución despachador de eventos
      SwingUtilities.invokeLater(
         new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
            public void run() // actualiza areaPantalla
            {
               areaPantalla.append( mensajeAMostrar );
               areaPantalla.setCaretPosition(
                  areaPantalla.getText().length() );
            }
         }  // fin de la clase interna
      ); // fin de la llamada a SwingUtilities.invokeLater
   }
   public static void main( String args[] )
   {
      JFrame.setDefaultLookAndFeelDecorated(true);
      Cliente aplicacion = new Cliente();
      aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      aplicacion.esperarPaquetes();
   }

}  // fin de la clase Cliente

Descargar código fuente

Los ejercicios utilizados en este post están basados en ejemplos del libro Cómo programar en Java de Deitel, y por lo tanto están bajo la licencia que esta editorial disponga.

19 Comentarios | deja el tuyo

19 Comentarios en “[código] Uso de Datagramas en Java (Protocolo UDP)”

  1. Frank dice:

    olaa estoy interesado en el tema y la vez tengo muchas dudas, xq el ejemplo si me funciona pero solo en modo localhost, que podria implementar al codigo para q, yo conectado a mi pc pueda acceder a otra (Cliente) necesito ayuda…, mas detalles:
    mi pc(Servidor):
    ip:192.168.40.100
    hostname:Rodriguez-PC
    puerto:(indefinido) no lo tengo definido
    otra pc(Cliente):
    ip:10.0.0.4
    hostname:
    puerto:(indefinido) no lo tengo definido
    en q parte del codigo modifico y como lo modifico. ¿Puedo comunicarme a travez de internet? tipo un antivirus. gracias de antemano mi correo: not_alone_411@hotmail.com

  2. maicol dice:

    hola tengo una duda como hago que un servidor pueda enviar un paquete a varios clientes al mismo tiempo.
    en protocolo udp.

    gracias de antemano.
    mi correo: maicol.1991@hotmail.com

  3. Andrew dice:

    Hola Amigo, necesito si me puedes colaborar con lo siguiente:

    Necesito una aplicación en java cliente-servidor que simule un servidor DHCP, en la que basicamente el cliente deberá realizar la solicitud de dirección IP a la máquina servidora implementando una petición broadcast y enviando un mensaje codificado con la dirección MAC el cual reconocerá su servidor. Su servidor renviará una dirección ip seleccionada de una lista que al configurar su servidor será definido por el usuario que levanta el servicio.La dirección MAC deberá ser tomada dinámicamente de la máquina cliente. No debe ser digitada por el usuario

    gracias de antemano.

    Correo: carlitosbega@hotmail.com

¡Déjanos tu comentario!