jueves, 25 de junio de 2015

1. Definición: Concepto y estructura

Un datagrama es un fragmento de paquete (análogo a un telegrama) que es enviado con la suficiente información para que la red pueda simplemente encaminar el fragmento hacia el equipo terminal de datos receptor, de manera independiente a los fragmentos restantes. Esto puede provocar una recomposición desordenada o incompleta del paquete en el ETD destino.

udp.jpg
Figura Nº 5: Protocolo UDP
Los datagramas también son la agrupación lógica de información que se envía como una unidad de capa de red a través de un medio de transmisión sin establecer con anterioridad un circuito virtual. Los datagramas IP son las unidades principales de información de Internet. Los términos trama, mensaje, paquete y segmento también se usan para describir las agrupaciones de información lógica en las diversas capas del modelo de referencia OSI y en los diversos círculos tecnológicos.
Algunos Protocolos basados en datagramas son IPX, UDP, IPoAC. Los datagramas tienen cabida en los servicios de red no orientados a la conexión (como por ejemplo UDP) o Datagrama.

IPX
El protocolo Intercambio de Paquetes Entre Redes (IPX) es la implementación del protocolo IDP (Internet Datagram Protocol) de Xerox. Es un protocolo de datagramas rápido orientado a comunicaciones sin conexión que se encarga de transmitir datos a través de la red, incluyendo en cada paquete la dirección de destino.Pertenece a la capa de red (nivel 3 del modelo OSI) y al ser un protocolo de datagramas es similar (aunque más simple y con menor fiabilidad) al protocolo IP del TCP/IP en sus operaciones básicas pero diferente en cuanto al sistema de direccionamiento, formato de los paquetes y el ámbito general Fue creado por el ing. Alexis G.Soulle
UDP
User Datagram Protocol (UDP) es un protocolo del nivel de transporte basado en el intercambio de datagramas (Paquete de datos). Permite el envío de datagramas a través de la red sin que se haya establecido previamente una conexión, ya que el propio datagrama incorpora suficiente información de direccionamiento en su cabecera. Tampoco tiene confirmación ni control de flujo, por lo que los paquetes pueden adelantarse unos a otros; y tampoco se sabe si ha llegado correctamente, ya que no hay confirmación de entrega o recepción. Su uso principal es para protocolos como DHCP, BOOTP, DNS y demás protocolos en los que el intercambio de paquetes de la conexión/desconexión son mayores, o no son rentables con respecto a la información transmitida, así como para la transmisión de audio y vídeo en tiempo real, donde no es posible realizar retransmisiones por los estrictos requisitos de retardo que se tiene en estos casos.
IPoAC
IP sobre palomas mensajeras es un protocolo de red creado en 1 de abril de 1990 para la transmisión de datagramas del protocolo IP mediante palomas mensajeras y definido en la recomendación RFC 1149. El 1 de abril de 1999 se publicó la recomendación RFC 2549, una extensión de la anterior denominada IP sobre palomas mensajeras con calidad de servicio.
EstructuraLa estructura de un datagrama es: cabecera y datos.

datagrama_UDP_2.png

Significado de los diferentes campos:

  • Puerto de origen: es el número de puerto relacionado con la aplicación del remitente del segmento UDP. Este campo representa una dirección de respuesta para el destinatario. Por lo tanto, este campo es opcional. Esto significa que si el puerto de origen no está especificado, los 16 bits de este campo se pondrán en cero. En este caso, el destinatario no podrá responder (lo cual no es estrictamente necesario, en particular para mensajes unidireccionales).
  • Puerto de destino: este campo contiene el puerto correspondiente a la aplicación del equipo receptor al que se envía.
  • Longitud: este campo especifica la longitud total del segmento, con el encabezado incluido. Sin embargo, el encabezado tiene una longitud de 4 x 16 bits (que es 8 x 8 bits), por lo tanto la longitud del campo es necesariamente superior o igual a 8 bytes.
  • Suma de comprobación: es una suma de comprobación realizada de manera tal que permita controlar la integridad del segmento.

EnrutamientoEnrutar es el proceso de selección de un camino para el envío de paquetes. La computadora que hace esto es llamada Router.

image014.jpg

En general se puede dividir el enrutamiento en Entrega Directa y Entrega Indirecta. La Entrega Directa es la transmisión de un Datagrama de una maquina a otra dentro de la misma red física. La Entrega Indirecta ocurre cuando el destino no está en la red local, lo que obliga al Host a enviar el Datagrama a algún Router intermedio. Es necesario el uso de mascaras de subred para saber si el Host destino de un Datagrama esta o no dentro de la misma red física.
Algoritmo de Enrutamiento

Ruta Datagrama(Datagrama) {Extrae de la Cabecera de Datagrama la dirección de destino D;Extrae de D el prefijo de Red N;Si N corresponde a cualquier dirección directamente conectada EntoncesEnvía el Datagrama a D sobre la Red N;SinoSi en la tabla hay una ruta especifica para D EntoncesEnvía Datagrama al salto siguiente especificado;SinoSi En la tabla hay una ruta para la red N EntoncesEnvía Datagrama al salto siguiente especificado;SinoSi En la tabla hay una ruta por defecto EntoncesEnvía el Datagrama a la dirección por defecto;SinoDeclarar Fallo de Enrutamiento;FsiFsiFsiFsi}

PuertosUDP utiliza puertos para permitir la comunicación entre aplicaciones. El campo de puerto tiene una longitud de 16 bits, por lo que el rango de valores válidos va de 0 a 65.535. El puerto 0 está reservado, pero es un valor permitido como puerto origen si el proceso emisor no espera recibir mensajes como respuesta.

  • Los puertos 1 a 1023 se llaman puertos "bien conocidos" y en sistemas operativos tipo Unix enlazar con uno de estos puertos requiere acceso como superusuario.
  • Los puertos 1024 a 49.151 son puertos registrados.
  • Los puertos 49.152 a 65.535 son puertos efímeros y son utilizados como puertos temporales, sobre todo por los clientes al comunicarse con los servidores.

2. User Datagram Protocol (UDP)

2.1 Visión general

El protocolo UDP (UserDatagram Protocol) es un protocolo no orientado a conexión de la capa de transporte del modelo TCP/IP, lo que significa que nogarantizar ni la entrega de paquetes ni que los paquetes lleguen en orden secuencial, donde el control sobre el destino final de un paquete UDP recae en el equipo que lo envía.

Sin_título1.png
Figura Nº 7: UDP en una red pueden ser poco fiables
Dado la probabilidad de pérdida de paquetes de datos, puede parecer extraño que a nadie se le ocurra utilizar un sistema tan poco fiable, aparentemente anárquica. De hecho, hay muchas ventajas al usar UDP que pueden no ser evidentes a primera vista.

  • UDP puede ser más eficiente que la entrega garantizada de flujos de datos de. Si la cantidad de datos es pequeña y los datos se envían con frecuencia, tiene sentido usarla para evitar la sobrecarga de entrega garantizada.


  • A diferencia de TCP, que establecen una conexión, UDP causa menos gastos generales. Si la cantidad de datos que se envían es pequeña y los datos se envían con frecuencia, la sobrecarga de establecer una conexión no puede valer la pena. UDP puede ser preferible en este caso, sobre todo si se envían los datos de un gran número de máquinas a una central, en cuyo caso la suma total de todas estas conexiones pueden provocar una sobrecarga considerable.


  • Las aplicaciones en tiempo real pueden ser candidatos para usar UDP, ya que hay menos retrasos debido a la comprobación de errores y control de flujo de TCP. Los Paquetes UDP pueden ser utilizados para saturar el ancho de banda disponible para ofrecer grandes cantidades de datos. Además, si se pierden algunos datos, pueden ser sustituidos por el siguiente grupo de paquetes con información actualizada, eliminando la necesidad de volver a enviar los datos antiguos.


  • Los sockets UDP puede recibir datos de más de un host. Si hay varias máquinasdebe haber comunicación, entonces UDP puede ser más conveniente que otros mecanismos como TCP.


  • Algunos protocolos de red especificar UDP como mecanismo de transporte, que requiriendo su uso.


Un socket es una referencia indirecta a un puerto particular usada por el proceso receptor en la máquina receptora.

El envío de datagramas es similar a enviar una carta a través del servicio postal: El orden de salida no es importante y no está garantizado, y cada mensaje es independiente de cualquier otro.
En las comunicaciones basadas en datagramas como las UDP, el paquete de datagramas contiene el número de puerto de su destino y el UDP encamina el paquete a la aplicación apropiada. Como en la figura Nº 8

Comunicación_basada_en_datagramas.png

Figura Nº 8: Comunicación basada en datagramasUn datagrama enviado mediante UDP es trasmitido desde un proceso emisor a un proceso receptor sin reconocimiento o recomprobaciones. Si tiene lugar un fallo, el mensaje puede no llegar. Un datagrama es transmitido entre procesos cuando un proceso lo envía y otro proceso lo recibe. Cualquier proceso que necesite enviar o recibir mensajes debe en primer lugar crear un socket a una dirección de Internet y un puerto local. Un servidor enlazará ese socket a un puerto servidor - uno que se hace conocido a los clientes de manera que puedan enviar mensajes al mismo. Un cliente enlaza su socket a cualquier puerto local libre. El método receptor devuelve la dirección de Internet y el puerto del emisor, además del mensaje, permitiendo a los receptores enviar una respuesta.


image010.jpg
Figura Nº 9: un servidor utiliza dos sockets: uno para aceptar la conexión y el otro para enviar / receptor
Las clases Java para establecer comunicaciones mediante datagramas son:

  • java.net.DatagramPacket
  • java.net.DatagramSocket




2.2 Clase DatagramPacket


La clase DatagramPacket representa un paquete de datos destinados a la transmisión mediante el uso de UDP. Los paquetes son contenedores de una pequeña secuencia de bytes, e incluyen información de direccionamiento, como una dirección IP y un puerto.
Sin_título_2.png
Figura Nº 10: DatagramPacket
El significado de los datos almacenados en un DatagramPacket está determinado por su contexto. Cuando un DatagramPacket se ha leído desde un socket UDP, la dirección IP del paquete representa la dirección del remitente (lo mismo con el número de puerto). Sin embargo, cuando un DatagramPacket es usado para enviar un paquete UDP, la dirección IP almacenada en DatagramPacket representa la dirección del destinatario (lo mismo con el número de puerto). Esta inversión de sentido es importante Recuerde uno no querrá enviar un paquete de regreso a uno mismo.
2.2.1 Creando un DatagramPacket
Hay dos razones para crear un nuevo DatagramPacket:
I. Para enviar datos a una máquina remota usando UDP
II. Para recibir los datos enviados por una máquina remota usando UDP
La clase DatagramPacket proporciona un constructor que permite crear instancias de un array de bytes para el mensaje, la longitud del mensaje, la dirección Internet y el puerto local del socket de destino, de la siguiente forma:

Constructores
La elección del constructor DatagramPacket es determinada por su finalidad.
Cada constructor requiere la especificación de un conjunto de bytes, el cual se utilizará para almacenar el contenido del paquete UDP, y la longitud del paquete de datos.
Para crear un DatagramPacket para la recepción de paquetes UDP entrantes, el siguiente constructor debe ser usado:DatagramPacket(byte[] buffer, int length).Por ejemplo:DatagramPacket packet = new DatagramPacket(new byte[256], 256);
Para enviar un DatagramPacket a una máquina remota, es preferible utilizar el siguientes constructor:DatagramPacket(byte[] buffer, int length, InetAddress dest_addr, int dest_port).Por ejemplo:InetAddress addr = InetAddress.getByName("192.168.0.1")DatagramPacket packet = new DatagramPacket ( new byte[128], 128, addr, 2000);
2.2.2 Usando un DatagramPacketLa clase DatagramPacket proporciona algunos métodos importantes que permiten a: la dirección remota, puerto remoto, los datos (como un bytes de array), y la longitud del paquete puedan ser recuperado. A partir de JDK 1.1, hay también métodos para modificar estos, a través de un método set correspondiente. Esto significa que uno recibepaquetes que puedan ser reutilizados. Por ejemplo, el contenido de un paquete puede ser reemplazado y enviado de vuelta al remitente. Esto ahorra el tener que reiniciar la información de direccionamiento, la dirección y el puerto del paquete que ya está establecido en el remitente.

Métodos

  • InetAddress getAddress() - devuelve la dirección IP desde que unDatagramPacket fue enviado, o (si el paquete va a ser enviado a una máquina remota), la dirección IP de destino.
  • byte [] getData () - devuelve el contenido de la DatagramPacket, representado como una matriz de bytes.
  • int getLength int () - devuelve la longitud de los datos almacenados en un DatagramPacket. Esto puede ser menor que el tamaño real del búfer de datos
  • int getPort () - devuelve el número de puerto desde donde se envió un DatagramPacket, o (si el paquete va a ser enviado a una máquina remota), el número de puerto de destino.
  • void setAddress (InetAddress addr) - asigna una nueva dirección de destino a un DatagramPacket.
  • void setData (byte [] buffer) - asigna un buffer de datos nuevos a la DatagramPacket.
  • void SetLength (int length) - asigna una nueva longitud de la DatagramPacket.
  • Void setPort (int port) - asigna un puerto de destino a un nuevo DatagramPacket.

2.3 Clase DatagramSocket


La clase DatagramSocket proporciona acceso a un socket UDP, lo que permite que los paquetes UDP puedan ser enviados y recibidos. Un DatagramPacket se utiliza para representar un paquete UDP, y debe ser creado antes de recibir los paquetes. El mismo DatagramSocket puede ser usado para recibir los paquetes tanto como para enviarlos.
Sin embargo, las operaciones de lectura son de bloqueo, lo que significa que la aplicacióncontinuara esperando hasta que llega un paquete. Ya que los paquetes UDP no garantizan la entrega, esto puede causar que una aplicación se detenga si el remitente no vuelva a enviar los paquetes. Ya que los paquetes UDP no garantizan la entrega, esto puede originar que una aplicación se detenga si el remitente no vuelva a enviar los paquetes.
2.3.1 Creando un DatagramSocketA DatagramSocket puede ser utilizado para enviar y recibir paquetes. Cada DatagramSocket se une a un puerto en la máquina local, el cual es usado para dirigir a los paquetes. El número de puerto necesita no ser el mismo número de la máquina remota, pero si la aplicación es un servidor UDP, se suelen elegir un número de puerto específico. Si el DatagramSocket está destinado a ser un cliente, yno necesita que se una a un número de puerto específico, un constructor en blanco puede ser especificado.
Constructor
Para crear un DatagramSocket cliente, el siguiente constructor es usado: DatagramSocket () throws java.net.SocketException.
Para crear un server Datagram Socket, el siguiente constructor es usado: que toma como parámetro el puerto al que el servicio UDP será obligado: 
DatagramSocket (int puerto) throws java.net.SocketException

2.3.2 Usando un DatagramSocketDatagramSocket se utiliza para recibir los paquetes UDP entrantes y salientes para enviar paquetes UDP. Proporciona métodos para enviar y recibir paquetes, así también como especificar un valor de tiempo de espera cuando nonblocking I/O está utilizando, para inspeccionar y modificar el máximo tamaño de los paquetes UDP, y cerca del zócalo.

Métodos

  • void close () - cierra un socket, y se desliga del puerto local.
  • void connect (InetAddress remote_addr remote_port int) – restringe el acceso a la dirección especificada a distancia y el puerto. La designación es un término equivocado, ya que UDP en realidad no crear una "conexión" entre una máquina y otra. Sin embargo, si este método se utiliza, hace que las excepciones que se produce si se intenta enviar paquetes a,o leer los paquetes de cualquier otro host y el puerto a los especificados.
  • void disconnect() - desconecta el DatagramSocket.
  • InetAddress getInetAddress () - Devuelve la dirección remota a la que el socket está conectado, o null si no existe ninguna tal conexión.
  • int getPort () - devuelve el puerto remoto al que está conectado el socket, o -1 si no existe dicha conexión.
  • InetAddress getLocalAddress () - devuelve la dirección local a la que el socket esta enlazado.
  • int getLocalPort () - devuelve el puerto local al que está enlazado el conector.
  • int getReceiveBufferSize () throws java.net.SocketException – devuelve el tamaño máximo del búfer utilizado para los paquetes UDP entrantes.
  • int getSendBufferSize () throws java.net.SocketException - devuelve el tamaño máximo de búfer utilizado para paquetes UDP salientes.
  • getSoTimeout int () throws java.net.SocketException - devuelve el valor de la opción de conector de tiempo de espera. Este valor se utiliza para determinar el número de milisegundos que una operación de lectura bloqueara antes de lanzar un java.io.InterruptedIOException. De manera predeterminada, este valor será igual a cero, lo que indica que el bloqueo de E / S se utilizará.
  • void receive (DatagramPacket packet)) throws java.io.IOException- lee un paquete UDP y almacena el contenido en el paquete especificado. La dirección y el puerto.


2.4 Escuchar paquetes UDP


Antes de que una aplicación pueda leer los paquetes UDP enviados por equipos remotos, esta debe de estar vinculada a un puerto UDP local utilizando DatagramSocket, y crear un DatagramPacket que actuará como un contenedor de datos del paquete UDP. La figura muestra la relación entre un paquete UDP, y las diferentes clases de Java utilizada para el proceso, y la aplicación real.



Escuchar_paquetes_UDP.png
Figura Nº 11: Los paquetes UDP son recibidos por un DatagramSocket y se traducen en objeto DatagramPacket.
Cuando una aplicación quiere leer los paquetes UDP, llama al método DatagramSocket.receive, que copia un paquete UDP en el DatagramPacket especifico. El contenido de la DatagramPacket es procesado y el proceso se repite según sea necesario.
El siguiente fragmento de código ilustra este proceso:

DatagramPacket packet = new DatagramPacket (new byte[256], 256);DatagramSocket socket = new DatagramSocket(2000);boolean finished = false;while (! finished ){socket.receive (packet);// process the packet}socket.close();

Cuando se procesa el paquete, la aplicación debe trabajar directamente con un array de bytes. Sin embargo, si la aplicación se adecua más a la lectura de textos, se puede utilizar las clases del paquete de Java I/O para convertir un array de bytes a otro tipo de stream o lector. Al conectar un ByteArrayInputStream con el contenido de un datagrama y luego a otro tipo de InputStream o un InputStreamReader, se puede acceder al contenido de los paquetes UDP con relativa facilidad. Muchos desarrolladores prefieren usar los stream de Java I/O para procesar data, usando un DataInputStream o un BufferedReader para acceder al contenido de las matrices de bytes.

Sin_título_3.png
Figura Nº 12: La lectura de un paquete UDP se ha simplificado mediante la aplicación de los streams de entrada.

Por ejemplo, para conectar un DataInputStream con el contenido de un DatagramPacket, el siguiente código puede ser usado :

ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData() );DataInputStream din = new DataInputStream (bin);// Read the contents of the UDP packet.......


Figura_Nº_13.png
Figura Nº 13: Las estructuras de datos en los programas de emisor y receptor

El flujo del programa en el emisor y receptor

Remitente del programaCrear un socket de datagramas y vincularlo o cualquier puerto local.Colocar la data en una matriz de bytes.
  1. Crear un paquete de datagramas, especificando la matriz de datos y la dirección del receptor.
  2. Invocar el método de envío del socket con una referencia al paquete de datagramas.
Receptor del programaCrear un socket de datagrama y enlazarlo a un puerto local específico.
  1. Crear una matriz de bytes para la recepción de los datos.
  2. Crear un paquete de datagramas, especificando la matriz de datos.
  3. Invocar el método de recepción del socket con una referencia a los paquetes de datagramas.

2.5 Enviar paquetes UDP


La misma interfaz (DatagramSocket) empleada para recibir paquetes UDP también se utiliza para enviarlos. Cuando se envía un paquete, la aplicación debe crear un DatagramPacket, establecer la dirección y el puerto de la información, y escribir los datos destinados a la transmisión a su array de bytes. Si está respondiendo a un paquete recibido, la dirección y la información del puerto ya estará almacenada, y sólo los datosnecesitan ser sobrescritos. Una vez que el paquete está listo para la transmisión, el método de envío deDatagramSocket es invocado, y un paquete UDP se envía.
envioUDP.JPG

El siguiente fragmento de código ilustra este proceso:

DatagramSocket socket = new DatagramSocket(2000);
DatagramPacket packet = new DatagramPacket (new byte[256], 256);
packet.setAddress ( InetAddress.getByName ( somehost ) );
packet.setPort ( 2000 );
boolean finished = false;
while !finished )
{
// Escribir datos en el buffer del paquete
.........
socket.send (packet);
/ / Hacer otra cosa, como leer los paquetes, o revisar para
/ / ver si hay más paquetes a enviar
.........
}
socket.close();




2.6 Ejemplo de protocolo de datagramas de usuario


Para demostrar cómo los paquetes UDP se envían y reciben, vamos a compilar y ejecutar dos pequeños ejemplos. El primero se enlazará a un puerto local, leerá un paquete, y mostrará su contenido e información de direccionamiento. El segundo ejemplo enviará el paquete leído por el primero.
tecnologia_bigger.jpg


Cómo funciona PacketReceiveDemo 
La mayoría del código se explica por sí mismo, o es similar a los fragmentos de código anterior. Sin embargo, los lectores pueden beneficiarse de un examen más detenido. 

La aplicación se inicia mediante el enlace a un puerto específico, 2000. Las aplicaciones que ofrecen un servicio generalmente se enlazan a un puerto específico. Cuando actúa como un receptor, tu aplicación debe elegir un número de puerto específico, por lo que el emisor puede enviar paquetes UDP a este puerto. A continuación, la aplicación elabora un DatagramPacket para el almacenamiento de los paquetes UDP, y crea un nuevo buffer para almacenar los paquetes de datos.
DatagramSocket socket = new DatagramSocket (2000); 
System.out.println ("Enlazado a un puerto local" + socket.getLocalPort ()); 
DatagramPacket packet = new DatagramPacket (new byte [256], 256);

Ahora la aplicación está lista para leer un paquete. La operación de lectura está bloqueando, por lo que hasta que un paquete llega, el servidor espera. Cuando un paquete es entregado con éxito a la aplicación, la información de direccionamiento para el paquete se muestra de manera que se puede determinar de dónde vino.
socket.receive (packet); 
InetAddress remote_addr packet.getAddress = (); 
System.out.println ("Enviado por:" + remote_addr.getHostAddress ()); 
System.out.println ("Enviar a:" + packet.getPort ());

Para facilitar el acceso a los contenidos del paquete UDP, la aplicación utiliza un ByteArrayInputStream para leer en el paquete. Leyendo un carácter a la vez, el programa muestra el contenido del paquete y luego termina. Tenga en cuenta que los caracteres Unicode, que son representados por algo más que un solo byte, no se pueden escribir de esta manera.
ByteArrayInputStream bin = new ByteArrayInputStream 
(Packet.getData ()); 
for (int i = 0; i <packet.getLength (); i++){ 
int data = bin.read (); 
if (data == -1) 
break; 
else 
System.out.print ((char) data); 
}
 tecnologia_bigger.jpg



Cómo funciona PacketSendDemo
El segundo ejemplo utiliza UDP para comunicarse con el primer ejemplo. Este ejemplo actúa como el remitente, enviando un paquete UDP al receptor, que contiene un mensaje de felicitación en texto ASCII.
A pesar de que utiliza algunas clases similares (DatagramSocket, DatagramPacket), estas son empleadas de una manera ligeramente diferente.

La aplicación se inicia enlazando un socket UDP a un puerto local, que se utilizará para enviar el paquete de datos. A diferencia de la demostración del receptor, no importa que puerto local se está utilizando. De hecho, cualquier puerto libre es un candidato, y es posible que la ejecución de la aplicación varias veces resultara en números de puerto diferentes. Después de enlazarse a un puerto, el número de puerto se muestra para demostrarlo.
DatagramSocket socket = new DatagramSocket();System.out.println ("Enlazado a Puerto local " +socket.getLocalPort());

Antes de enviar los datos, necesitamos crear un DatagramPacket. En primer lugar, unByteArrayOutputStream es utilizado para crear una secuencia de bytes. Una vez completado esto, el array de bytes se pasa al constructor DatagramPacket.
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintStream pout = new PrintStream (bout);
pout.print ("Saludos!");
byte[] barray = bout.toByteArray();
DatagramPacket packet = new DatagramPacket( barray, barray.length );

Ahora que el paquete tiene algunos datos, necesita ser direccionado correctamente. Al igual que con un mensaje de correo, si carece de información correcta sobre la dirección no se puede entregar. Empezamos por obtener una InetAddress de la máquina remota, y luego mostrar su dirección IP. Este InetAddress es pasado al método setAddress de DatagramPacket, asegurando que llegará a la máquina correcta. Sin embargo, debemos ir un paso más allá y especificar un número de puerto. En este caso, el puerto 2000 coincide, ya que el receptor estará enlazado a ese puerto.
System.out.println ("Buscando nombre de host" + hostname);
InetAddress remote_addr = InetAddress.getByName(hostname);
System.out.println ("Nombre de host resuelto como" + remote_addr.getHostAddress());
packet.setAddress (remote_addr);
packet.setPort (2000);

El paso final, después de todo este trabajo, es enviar el paquete. Este es el paso más sencillo de todos, simplemente invocar el método de envío de DatagramSocket. Una vez más, recuerde: no hay ninguna garantía de entrega, así que es posible que un paquete se pierda en el tránsito. Una aplicación más robusta intentaría leer un acuse de recibo y reenviar el mensaje si se hubiera perdido.
socket.send(packet);