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.

18 Comentarios | deja el tuyo

18 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

¡Déjanos tu comentario!